From 2565837c0a7de676b6f565d829128b7a7913b275 Mon Sep 17 00:00:00 2001 From: Chad Crawford Date: Wed, 22 Jul 2026 16:34:57 -0400 Subject: [PATCH 1/5] emacs: add vs2008 theme and switch to vertico completion Replace ivy with vertico + orderless + marginalia, load a new vs2008 custom theme, and install the fonts (cozette, nerd-fonts.cousine) the config relies on. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/development/default.nix | 1 + apps/development/emacs/default.nix | 6 + apps/development/emacs/early-init.el | 5 + apps/development/emacs/home.nix | 1 + apps/development/emacs/init.el | 17 +- apps/development/emacs/themes/vs2008-theme.el | 229 ++++++++++++++++++ 6 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 apps/development/emacs/themes/vs2008-theme.el diff --git a/apps/development/default.nix b/apps/development/default.nix index 257500f..2e299c6 100644 --- a/apps/development/default.nix +++ b/apps/development/default.nix @@ -134,6 +134,7 @@ in { inherit tags; nixos = { pkgs, ... }: { fonts.packages = with pkgs; [ + nerd-fonts.cousine courier-unicode ]; }; diff --git a/apps/development/emacs/default.nix b/apps/development/emacs/default.nix index 4fc2d09..1b7da2b 100644 --- a/apps/development/emacs/default.nix +++ b/apps/development/emacs/default.nix @@ -7,6 +7,12 @@ inputs.emacs-overlay.overlay ]; }; + nixos = { pkgs, ... }: { + # Cozette bitmap font used by the default face in init.local.el. + # Installed here so every host with emacs (including the workspace + # VMs) gets the font, not just hosts that enable kitty. + fonts.packages = [ pkgs.cozette ]; + }; home = import ./home.nix; }; } diff --git a/apps/development/emacs/early-init.el b/apps/development/emacs/early-init.el index 0b16d3d..779489a 100644 --- a/apps/development/emacs/early-init.el +++ b/apps/development/emacs/early-init.el @@ -11,4 +11,9 @@ (set-frame-parameter nil 'alpha-background 95) (add-to-list 'default-frame-alist '(alpha-background . 95)) +;; theme +(add-to-list 'custom-theme-load-path + (expand-file-name "themes" user-emacs-directory)) +(load-theme 'vs2008 t) + ;;; early-init.el ends here diff --git a/apps/development/emacs/home.nix b/apps/development/emacs/home.nix index 5eb87d3..3767dd1 100644 --- a/apps/development/emacs/home.nix +++ b/apps/development/emacs/home.nix @@ -15,6 +15,7 @@ in { "${config.home.homeDirectory}/.emacs.d/early-init.el" = { source = ./early-init.el; }; "${config.home.homeDirectory}/.emacs.d/init.el" = { source = ./init.el; }; "${config.home.homeDirectory}/.emacs.d/lisp" = { source = ./lisp; recursive = true; }; + "${config.home.homeDirectory}/.emacs.d/themes" = { source = ./themes; recursive = true; }; }; packages = with pkgs; [ ispell diff --git a/apps/development/emacs/init.el b/apps/development/emacs/init.el index 91d6bcf..2cacda2 100644 --- a/apps/development/emacs/init.el +++ b/apps/development/emacs/init.el @@ -1,7 +1,6 @@ ;; Add LPA (require 'package) ;; You might already have this line -(package-initialize) (unless package-archive-contents (package-refresh-contents)) (unless (package-installed-p 'use-package) (package-install 'use-package)) @@ -69,10 +68,20 @@ (use-package projectile-ripgrep :ensure t) -;; IVY -(use-package ivy +;; Completion framework +(use-package vertico :ensure t - :config (ivy-mode)) + :config (vertico-mode)) + +(use-package orderless + :ensure t + :custom + (completion-styles '(orderless basic)) + (completion-category-overrides '((file (styles basic partial-completion))))) + +(use-package marginalia + :ensure t + :config (marginalia-mode)) ;; MAGIT (use-package magit diff --git a/apps/development/emacs/themes/vs2008-theme.el b/apps/development/emacs/themes/vs2008-theme.el new file mode 100644 index 0000000..2d14af4 --- /dev/null +++ b/apps/development/emacs/themes/vs2008-theme.el @@ -0,0 +1,229 @@ +;;; vs2008-theme.el --- Visual Studio 2008 default light color scheme -*- lexical-binding: t; -*- + +;; Author: generated for Chad +;; Keywords: faces, theme +;; Version: 1.0 + +;;; Commentary: +;; +;; A faithful port of the default Microsoft Visual Studio 2008 text-editor +;; color scheme. Palette derived directly from VS screenshots: +;; +;; plain text #000000 on #FFFFFF +;; keyword #0000FF (blue) +;; comment #008000 (green) +;; doc comment #808080 (gray, /// XML doc) +;; string #A31515 (maroon) +;; user type #2B91AF (teal) +;; number #000000 (VS 2008 does not color numbers by default) +;; XML/HTML tag #A31515 (maroon) +;; XML attr #FF0000 (red) +;; XML attr val #0000FF (blue) +;; tag/<>/= #0000FF (blue) +;; line numbers #2B91AF (teal) +;; selection #3399FF (blue) +;; +;; Install: drop this file in a directory on `custom-theme-load-path' and +;; (load-theme 'vs2008 t) + +;;; Code: + +(deftheme vs2008 + "Default Visual Studio 2008 light editor color scheme.") + +(let ((class '((class color) (min-colors 89))) + ;; --- core palette --- + (bg "#FFFFFF") + (fg "#000000") + (keyword "#0000FF") + (comment "#008000") + (doc "#808080") + (string "#A31515") + (type "#2B91AF") + (number "#000000") + (preproc "#0000FF") + ;; --- xml / html --- + (xml-tag "#A31515") + (xml-attr "#FF0000") + (xml-val "#0000FF") + (xml-delim "#0000FF") + ;; --- ui chrome (2008-era, not the 2012 #007ACC bar) --- + (linenum "#2B91AF") + (gutter-bg "#FFFFFF") + (region "#3399FF") + (region-fg "#FFFFFF") + (hl "#F5F5F5") + (paren "#BADFFF") + (ml-bg "#C9D5E8") + (ml-fg "#0A0A0A") + (ml-inact-bg "#EEF1F7") + (ml-inact-fg "#5A5A5A") + (border "#9EB6CE") + (warning "#FF0000") + (lazy "#FFFFAA")) + + (custom-theme-set-faces + 'vs2008 + + ;; --- base --- + `(default ((,class (:background ,bg :foreground ,fg)))) + `(cursor ((,class (:background ,fg)))) + `(region ((,class (:background ,region :foreground ,region-fg)))) + `(highlight ((,class (:background ,paren)))) + `(hl-line ((,class (:background ,hl)))) + `(fringe ((,class (:background ,bg :foreground ,fg)))) + `(vertical-border ((,class (:foreground ,border)))) + `(minibuffer-prompt ((,class (:foreground ,keyword :weight bold)))) + `(shadow ((,class (:foreground ,doc)))) + + ;; --- font-lock (syntax) --- + `(font-lock-keyword-face ((,class (:foreground ,keyword)))) + `(font-lock-builtin-face ((,class (:foreground ,keyword)))) + `(font-lock-constant-face ((,class (:foreground ,keyword)))) ; true/false/null + `(font-lock-preprocessor-face ((,class (:foreground ,preproc)))) + `(font-lock-comment-face ((,class (:foreground ,comment)))) + `(font-lock-comment-delimiter-face ((,class (:foreground ,comment)))) + `(font-lock-doc-face ((,class (:foreground ,doc)))) + `(font-lock-doc-markup-face ((,class (:foreground ,doc)))) + `(font-lock-string-face ((,class (:foreground ,string)))) + `(font-lock-type-face ((,class (:foreground ,type)))) + `(font-lock-function-name-face ((,class (:foreground ,fg)))) + `(font-lock-variable-name-face ((,class (:foreground ,fg)))) + `(font-lock-property-name-face ((,class (:foreground ,fg)))) + `(font-lock-property-use-face ((,class (:foreground ,fg)))) + `(font-lock-number-face ((,class (:foreground ,number)))) + `(font-lock-negation-char-face ((,class (:foreground ,fg)))) + `(font-lock-warning-face ((,class (:foreground ,warning :weight bold)))) + + ;; --- line numbers --- + `(line-number ((,class (:background ,gutter-bg :foreground ,linenum)))) + `(line-number-current-line ((,class (:background ,gutter-bg :foreground ,linenum :weight bold)))) + `(linum ((,class (:background ,gutter-bg :foreground ,linenum)))) + + ;; --- search / parens --- + `(isearch ((,class (:background ,region :foreground ,region-fg)))) + `(lazy-highlight ((,class (:background ,lazy :foreground ,fg)))) + `(show-paren-match ((,class (:background ,paren :weight bold)))) + `(show-paren-mismatch ((,class (:background ,warning :foreground ,bg :weight bold)))) + + ;; --- mode line (VS 2008 gray-blue chrome) --- + `(mode-line ((,class (:background ,ml-bg :foreground ,ml-fg :box (:line-width 1 :color ,border))))) + `(mode-line-inactive ((,class (:background ,ml-inact-bg :foreground ,ml-inact-fg :box (:line-width 1 :color ,border))))) + `(mode-line-buffer-id ((,class (:weight bold)))) + + ;; --- nXML --- + `(nxml-element-local-name ((,class (:foreground ,xml-tag)))) + `(nxml-tag-delimiter ((,class (:foreground ,xml-delim)))) + `(nxml-tag-slash ((,class (:foreground ,xml-delim)))) + `(nxml-attribute-local-name ((,class (:foreground ,xml-attr)))) + `(nxml-attribute-value ((,class (:foreground ,xml-val)))) + `(nxml-attribute-value-delimiter ((,class (:foreground ,xml-val)))) + `(nxml-namespace-attribute-xmlns ((,class (:foreground ,xml-attr)))) + `(nxml-comment-content-face ((,class (:foreground ,comment)))) + + ;; --- SGML / html-mode --- + `(sgml-namespace ((,class (:foreground ,xml-tag)))) + + ;; --- web-mode --- + `(web-mode-html-tag-face ((,class (:foreground ,xml-tag)))) + `(web-mode-html-tag-bracket-face ((,class (:foreground ,xml-delim)))) + `(web-mode-html-attr-name-face ((,class (:foreground ,xml-attr)))) + `(web-mode-html-attr-value-face ((,class (:foreground ,xml-val)))) + `(web-mode-comment-face ((,class (:foreground ,comment)))) + `(web-mode-string-face ((,class (:foreground ,string)))) + `(web-mode-keyword-face ((,class (:foreground ,keyword)))) + `(web-mode-type-face ((,class (:foreground ,type)))) + + ;; --- completion popup (subtle, period-appropriate) --- + `(completions-common-part ((,class (:foreground ,keyword)))) + `(tooltip ((,class (:background "#FFFFE1" :foreground ,fg)))) + + ;; --- diff --- + `(diff-added ((,class (:foreground ,comment :background "#E6FFE6")))) + `(diff-removed ((,class (:foreground ,warning :background "#FFE6E6")))) + `(diff-changed ((,class (:foreground "#B8860B" :background "#FFE6CC")))) + + ;; --- org mode --- + `(org-level-1 ((,class (:foreground ,keyword :weight bold :height 1.3)))) + `(org-level-2 ((,class (:foreground ,type :weight bold :height 1.2)))) + `(org-level-3 ((,class (:foreground ,comment :weight bold :height 1.1)))) + `(org-level-4 ((,class (:foreground ,string :weight bold)))) + `(org-code ((,class (:foreground ,string :background ,hl)))) + `(org-block ((,class (:background ,hl)))) + `(org-block-begin-line ((,class (:foreground ,comment :background ,hl)))) + `(org-block-end-line ((,class (:foreground ,comment :background ,hl)))) + + ;; --- magit --- + `(magit-diff-added ((,class (:foreground ,comment :background "#E6FFE6")))) + `(magit-diff-removed ((,class (:foreground ,warning :background "#FFE6E6")))) + `(magit-diff-context ((,class (:foreground ,fg)))) + `(magit-section-heading ((,class (:foreground ,keyword :weight bold)))) + `(magit-branch-local ((,class (:foreground ,type :weight bold)))) + `(magit-branch-remote ((,class (:foreground ,comment :weight bold)))) + + ;; --- error/warning/success --- + `(error ((,class (:foreground ,warning :weight bold)))) + `(warning ((,class (:foreground "#B8860B" :weight bold)))) + `(success ((,class (:foreground ,comment :weight bold)))) + + ;; --- flycheck/flymake --- + `(flycheck-error ((,class (:underline (:style wave :color ,warning))))) + `(flycheck-warning ((,class (:underline (:style wave :color "#B8860B"))))) + `(flycheck-info ((,class (:underline (:style wave :color ,type))))) + + ;; --- whitespace mode --- + `(whitespace-trailing ((,class (:background "#FFE6E6")))) + `(whitespace-tab ((,class (:foreground "#C0C0C0")))) + `(whitespace-space ((,class (:foreground "#D0D0D0")))) + + ;; --- misc --- + `(link ((,class (:foreground ,keyword :underline t)))) + + ;; --- eat terminal colors (ANSI colors for light background) --- + `(eat-term-font-0 ((,class (:background ,bg)))) + `(eat-term-bold ((,class (:weight bold)))) + + ;; Normal colors (0-7) + `(eat-term-color-0 ((,class (:foreground "#000000" :background "#000000")))) ; black + `(eat-term-color-1 ((,class (:foreground "#CD3131" :background "#CD3131")))) ; red + `(eat-term-color-2 ((,class (:foreground "#00AA00" :background "#00AA00")))) ; green + `(eat-term-color-3 ((,class (:foreground "#AA5500" :background "#AA5500")))) ; yellow/brown + `(eat-term-color-4 ((,class (:foreground "#0451A5" :background "#0451A5")))) ; blue + `(eat-term-color-5 ((,class (:foreground "#BC05BC" :background "#BC05BC")))) ; magenta + `(eat-term-color-6 ((,class (:foreground "#0598BC" :background "#0598BC")))) ; cyan + `(eat-term-color-7 ((,class (:foreground "#555555" :background "#555555")))) ; white (dark gray) + + ;; Bright colors (8-15) + `(eat-term-color-8 ((,class (:foreground "#666666" :background "#666666")))) ; bright black (gray) + `(eat-term-color-9 ((,class (:foreground "#E50000" :background "#E50000")))) ; bright red + `(eat-term-color-10 ((,class (:foreground "#00DD00" :background "#00DD00")))) ; bright green + `(eat-term-color-11 ((,class (:foreground "#DDDD00" :background "#DDDD00")))) ; bright yellow + `(eat-term-color-12 ((,class (:foreground "#0066FF" :background "#0066FF")))) ; bright blue + `(eat-term-color-13 ((,class (:foreground "#DD00DD" :background "#DD00DD")))) ; bright magenta + `(eat-term-color-14 ((,class (:foreground "#00DDDD" :background "#00DDDD")))) ; bright cyan + `(eat-term-color-15 ((,class (:foreground "#000000" :background "#000000")))) ; bright white (black) + ) + + (custom-theme-set-variables + 'vs2008 + `(frame-background-mode 'light))) + +;; Ensure cursor color is applied at the frame level, since +;; custom-theme-set-faces for 'cursor doesn't always override +;; the frame parameter left by previously loaded themes. +(defun vs2008--set-cursor-color (&optional _theme) + "Set cursor color when vs2008 theme is active." + (when (member 'vs2008 custom-enabled-themes) + (set-cursor-color "#000000"))) + +(add-hook 'after-init-hook #'vs2008--set-cursor-color) +(add-hook 'enable-theme-functions #'vs2008--set-cursor-color) + +;;;###autoload +(when (and (boundp 'custom-theme-load-path) load-file-name) + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide-theme 'vs2008) +(provide 'vs2008-theme) +;;; vs2008-theme.el ends here From f3d5f2720578ae43386bb141e0d3dff90e7adbb7 Mon Sep 17 00:00:00 2001 From: Chad Crawford Date: Wed, 22 Jul 2026 16:35:16 -0400 Subject: [PATCH 2/5] redshift: add app and enable warm night screen on odin Add a default-disabled apps.redshift (x11) that warms color temperature at night, and enable it on odin. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/display/default.nix | 23 ++++++++++++++++++++++- hosts/odin/default.nix | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/apps/display/default.nix b/apps/display/default.nix index 13b39e0..6997b41 100644 --- a/apps/display/default.nix +++ b/apps/display/default.nix @@ -1,4 +1,4 @@ -{ ... }: +{ lib, ... }: let tags = [ "display" ]; x11Tags = [ "x11" ]; @@ -48,6 +48,27 @@ in }; }; + # Redshift: shifts screen color temperature warmer at night. + # Default-disabled; enable per-host with `apps.redshift.enable = true` + # and override the placeholder latitude/longitude below. + apps.redshift = { + inherit systems; + tags = x11Tags; + enable = lib.mkDefault false; + home = { lib, ... }: { + services.redshift = { + enable = true; + # Default coordinates — override per host if needed. + latitude = lib.mkDefault 26.1418617; + longitude = lib.mkDefault (-80.1228234); + temperature = { + day = lib.mkDefault 6500; + night = lib.mkDefault 3700; + }; + }; + }; + }; + apps.picom = { inherit systems; tags = x11Tags; diff --git a/hosts/odin/default.nix b/hosts/odin/default.nix index 96c7fca..7a96f58 100644 --- a/hosts/odin/default.nix +++ b/hosts/odin/default.nix @@ -22,6 +22,8 @@ let nix-config = { # disable podman in favor of dumb docker... for now apps.podman.enable = false; + # warm screen at night + apps.redshift.enable = true; }; nixpkgs.packages.unfree = [ From 8a1b1bef165c1a6b8c68dc6ce5ebb12e1e3560f4 Mon Sep 17 00:00:00 2001 From: Chad Crawford Date: Wed, 22 Jul 2026 16:35:28 -0400 Subject: [PATCH 3/5] display: use flattened xfce/xorg package attributes nixpkgs moved these out of the xfce/xorg scopes: xfce.ristretto, xfce.thunar*, xfce.tumbler -> ristretto/thunar*/tumbler; xorg.xrdb, xorg.xrandr -> xrdb/xrandr (display + libvirtd guest). Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/display/default.nix | 8 ++++---- apps/display/x11/Xresources/default.nix | 2 +- apps/display/x11/default.nix | 4 ++-- apps/virt/libvirtd/default.nix | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/display/default.nix b/apps/display/default.nix index 6997b41..730342a 100644 --- a/apps/display/default.nix +++ b/apps/display/default.nix @@ -37,7 +37,7 @@ in inherit systems; tags = x11Tags; home = { pkgs, ... }: { - home.packages = [ pkgs.xfce.ristretto ]; + home.packages = [ pkgs.ristretto ]; }; }; @@ -83,12 +83,12 @@ in apps.thunar = { inherit systems tags; home = { pkgs, ... }: { - home.packages = [ pkgs.xfce.thunar ]; + home.packages = [ pkgs.thunar ]; }; nixos = { pkgs, ... }: { programs.thunar = { enable = true; - plugins = with pkgs.xfce; [ + plugins = with pkgs; [ thunar-archive-plugin thunar-volman thunar-media-tags-plugin @@ -100,7 +100,7 @@ in apps.tumbler = { inherit systems tags; home = { pkgs, ... }: { - home.packages = [ pkgs.xfce.tumbler ]; + home.packages = [ pkgs.tumbler ]; }; nixos = { services.tumbler.enable = true; diff --git a/apps/display/x11/Xresources/default.nix b/apps/display/x11/Xresources/default.nix index aec0480..1263329 100644 --- a/apps/display/x11/Xresources/default.nix +++ b/apps/display/x11/Xresources/default.nix @@ -16,7 +16,7 @@ in { "${dest}" = { text = Xresources; }; }; xsession.profileExtra = '' - ${pkgs.xorg.xrdb}/bin/xrdb -merge ${dest} + ${pkgs.xrdb}/bin/xrdb -merge ${dest} ''; }; }; diff --git a/apps/display/x11/default.nix b/apps/display/x11/default.nix index c394b5c..f4a73e3 100644 --- a/apps/display/x11/default.nix +++ b/apps/display/x11/default.nix @@ -67,7 +67,7 @@ in # to xrandr right after starting the xserver. displayManager.setupCommands = lib.mkIf (hasAttr "displays" host) - (mkXrandrCmd pkgs.xorg.xrandr host.displays); + (mkXrandrCmd pkgs.xrandr host.displays); }; }; home = { host, pkgs, ...}: { @@ -75,7 +75,7 @@ in xsession.initExtra = lib.mkIf (host.kind == "home-manager") (lib.mkBefore # Make this the highest priority item - (mkXrandrCmd pkgs.xorg.xrandr host.displays)); + (mkXrandrCmd pkgs.xrandr host.displays)); }; }; }; diff --git a/apps/virt/libvirtd/default.nix b/apps/virt/libvirtd/default.nix index 08e14e2..e1fe56b 100644 --- a/apps/virt/libvirtd/default.nix +++ b/apps/virt/libvirtd/default.nix @@ -23,7 +23,7 @@ systemd ripgrep sd - xorg.xrandr + xrandr ]; }; in From d0348b768f91a89f170fdebb3db00bbcb74df4ce Mon Sep 17 00:00:00 2001 From: Chad Crawford Date: Wed, 22 Jul 2026 16:35:35 -0400 Subject: [PATCH 4/5] odin: enable k3s Import the existing k3s.nix module into odin's configuration. Co-Authored-By: Claude Opus 4.8 (1M context) --- hosts/odin/nixos/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/odin/nixos/configuration.nix b/hosts/odin/nixos/configuration.nix index 29f98b7..0707047 100644 --- a/hosts/odin/nixos/configuration.nix +++ b/hosts/odin/nixos/configuration.nix @@ -5,6 +5,7 @@ ./virt.nix ./display.nix ./docker.nix + ./k3s.nix ./printing.nix # KVM Virtual Machine Configurations From 09f4f7997140a03d9d7ebb671a9960ba80ebfc9c Mon Sep 17 00:00:00 2001 From: Chad Crawford Date: Wed, 22 Jul 2026 16:35:35 -0400 Subject: [PATCH 5/5] ci: build with --keep-going so partial results still cache On a failed derivation, keep building everything that doesn't depend on it; cachix-action's daemon pushes each path as it's built, so a partial build still populates the cache and saves rebuild time on the next run. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/cachix.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 471bb16..aaac199 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -37,4 +37,8 @@ jobs: name: chadac-dotfiles authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - name: Build ${{ matrix.target }} - run: nix build --print-build-logs ".#${{ matrix.target }}" + # --keep-going: on a failed derivation, keep building everything that + # doesn't depend on it. cachix-action's daemon pushes each path as it's + # built, so even a partial/failed build still populates the cache and + # saves rebuild time on the next run. + run: nix build --print-build-logs --keep-going ".#${{ matrix.target }}"