diff options
25 files changed, 367 insertions, 251 deletions
diff --git a/modules/colors/base16/default.nix b/modules/colors/base16/default.nix index 1262b53..982113e 100644 --- a/modules/colors/base16/default.nix +++ b/modules/colors/base16/default.nix @@ -1,4 +1,7 @@ -# Provide options/configurations for other modules to use base16 colorschemes +# Shared base16 color scheme helpers. Not a module — pass the module arguments +# to it (`import <path> { inherit config lib pkgs; }`) to get +# `colorsWithHashPrefix` and a functor that renders a color template into a Nix +# store file. { config, lib, @@ -6,52 +9,40 @@ ... }: let - schemeFiles = { + availableColorSchemeFiles = { "onedark-dark" = ./onedark-dark.nix; }; - schemeFile = - schemeFiles.${config.colors.base16} or (throw "Unknown color scheme: ${config.colors.base16}"); + selectedColorSchemeFile = + availableColorSchemeFiles.${config.colors.base16} + or (throw "Unknown color scheme: ${config.colors.base16}"); - colors = import schemeFile { }; + selectedColorScheme = import selectedColorSchemeFile { }; + selectedColorSchemeColorNames = builtins.attrNames selectedColorScheme; - withHashtag = lib.mapAttrs (_: v: "#${v}") colors; - colorNames = builtins.attrNames colors; - - processTemplate = - template: + renderColorSchemeTemplate = + templateFileOrContent: let - content = if builtins.typeOf template == "path" then builtins.readFile template else template; - replaced = builtins.replaceStrings (map (name: "@@${name}@@") colorNames) (map ( - name: colors.${name} - ) colorNames) content; + templateContent = + if builtins.typeOf templateFileOrContent == "path" then + builtins.readFile templateFileOrContent + else + templateFileOrContent; in - replaced; + builtins.replaceStrings (map (colorName: "@@${colorName}@@") selectedColorSchemeColorNames) (map ( + colorName: selectedColorScheme.${colorName} + ) selectedColorSchemeColorNames) templateContent; in { - options = { - colors.base16 = lib.mkOption { - type = lib.types.str; - default = "onedark-dark"; - description = "Base16 color scheme to use"; - }; - - scheme = lib.mkOption { - type = lib.types.unspecified; - description = "Color scheme providing withHashtag and template function"; - }; - }; + colorsWithHashPrefix = lib.mapAttrs (_colorName: colorValue: "#${colorValue}") selectedColorScheme; - config = { - scheme = { - inherit withHashtag; - __functor = - self: - { - template, - extension ? "", - }: - pkgs.writeText "themed${extension}" (processTemplate template); - }; - }; + __functor = + _self: + { + templateFileOrContent, + fileExtension ? "", + }: + pkgs.writeText "color-scheme-themed${fileExtension}" ( + renderColorSchemeTemplate templateFileOrContent + ); } diff --git a/modules/colors/default.nix b/modules/colors/default.nix index 1bf48b5..b9009e9 100644 --- a/modules/colors/default.nix +++ b/modules/colors/default.nix @@ -1,7 +1,9 @@ -# Configuration wide colorscheme configurations -{ ... }: +# Configuration-wide color scheme selection. +{ lib, ... }: { - imports = [ - ./base16 - ]; + options.colors.base16 = lib.mkOption { + type = lib.types.str; + default = "onedark-dark"; + description = "Name of the base16 color scheme to use."; + }; } diff --git a/modules/communication/neomutt/account/sync-channel.nix b/modules/communication/neomutt/account/sync-channel.nix index 5af7443..7e538f2 100644 --- a/modules/communication/neomutt/account/sync-channel.nix +++ b/modules/communication/neomutt/account/sync-channel.nix @@ -4,11 +4,15 @@ name, ... }@inputs: +let + + mbsyncNamesFromName = (import ../lib.nix { inherit lib; }).mbsyncNamesFromName; +in { config = lib.mkIf config.enable { neomutt.extraConfig = let - mbsyncNames = (import ../lib.nix inputs).mbsyncNamesFromName name; + mbsyncNames = mbsyncNamesFromName name; in '' macro index,pager gs "<enter-command>set my_wait_key=$wait_key wait_key=no<enter><sync-mailbox><shell-escape>neomutt-sync ${mbsyncNames.channels.quick}<enter><sync-mailbox><enter-command>set wait_key=$my_wait_key<enter>" diff --git a/modules/communication/neomutt/mail/mbsync.nix b/modules/communication/neomutt/mail/mbsync.nix index 7bc72ce..f586538 100644 --- a/modules/communication/neomutt/mail/mbsync.nix +++ b/modules/communication/neomutt/mail/mbsync.nix @@ -3,8 +3,10 @@ config, lib, ... -}@inputs: +}: let + mbsyncNamesFromName = (import ../lib.nix { inherit lib; }).mbsyncNamesFromName; + mbsyncValue = value: if lib.isList value then @@ -26,7 +28,7 @@ let mbsyncAccount = account: let - mbsyncNames = (import ../lib.nix inputs).mbsyncNamesFromName account.name; + mbsyncNames = mbsyncNamesFromName account.name; in lib.concatStringsSep "\n" [ (mbsyncSection "IMAPAccount ${mbsyncNames.base}" ( @@ -86,9 +88,9 @@ let }) ]; - accounts = lib.filter ( - account: account.enable && account.mbsync.enable - ) lib.attrValues config.accounts.email.accounts; + accounts = lib.filter (account: account.enable && account.mbsync.enable) ( + lib.attrValues config.accounts.email.accounts + ); in { config = lib.mkIf config.communication.neomutt.enable { diff --git a/modules/desktop/eww/bar/bar.nix b/modules/desktop/eww/bar/bar.nix index 70bfbac..252811f 100644 --- a/modules/desktop/eww/bar/bar.nix +++ b/modules/desktop/eww/bar/bar.nix @@ -63,12 +63,10 @@ name = "eww-system-stats"; path = ./system-stats.lua; description = "Emit {cpu, ram, net} as JSON."; - luaPackages = ( - ps: [ - ps.lua-cjson - ps.luaposix - ] - ); + luaPackages = ps: [ + ps.lua-cjson + ps.luaposix + ]; deps = [ pkgs.iw pkgs.iproute2 @@ -82,12 +80,10 @@ name = "niri-status"; path = ./niri-status.lua; description = "Emit workspace and active window information list."; - luaPackages = ( - ps: [ - ps.lgi - ps.lua-cjson - ] - ); + luaPackages = ps: [ + ps.lgi + ps.lua-cjson + ]; deps = [ config.desktop.niri.package ]; gobjectIntrospection = true; }; diff --git a/modules/desktop/eww/bar/bar.yuck b/modules/desktop/eww/bar/bar.yuck index f8f48d0..dc2d575 100644 --- a/modules/desktop/eww/bar/bar.yuck +++ b/modules/desktop/eww/bar/bar.yuck @@ -29,61 +29,122 @@ (system-widget))) (defwidget workspaces-widget [workspaces] - (box :orientation "v" :space-evenly false :spacing 4 :halign "fill" :class "workspaces" + (box :orientation "v" + :space-evenly false + :spacing 4 + :halign "fill" + :class "workspaces" (for ws in workspaces (eventbox :onclick "niri msg action focus-workspace ${ws.idx}" - :cursor "pointer" :halign "fill" + :cursor "pointer" + :halign "fill" :tooltip "${ws.tooltip}" - (box :class "workspace-button ${ws.is_active ? 'active' : ''}" :halign "fill" + (box :class "workspace-button ${ws.is_active ? 'active' : ''}" + :halign "fill" (overlay :halign "fill" (image :class "workspace-icon" :path "${ws.icon}" - :image-width 20 :image-height 20) - (label :class "workspace-idx" :text "${ws.idx}" :halign "end" :valign "end"))))))) + :image-width 20 + :image-height 20) + (label :class "workspace-idx" + :text "${ws.idx}" + :halign "end" + :valign "end"))))))) (defwidget windows-widget [windows] - (box :orientation "v" :space-evenly false :spacing 4 :halign "center" :class "windows" :vexpand true + (box :orientation "v" + :space-evenly false + :spacing 4 + :halign "center" + :class "windows" + :vexpand true (for w in windows (eventbox :onclick "niri msg action focus-window --id ${w.id}" :cursor "pointer" :halign "fill" :tooltip "${w.app_id}: ${w.title != '' ? ' ' : ''}${w.title}" - (box :halign "fill" :class "window-button ${w.is_focused ? 'focused' : ''}" - (image :class "window-icon" :path "${w.icon}" :image-width 20 :image-height 20)))))) + (box :halign "fill" + :class "window-button ${w.is_focused ? 'focused' : ''}" + (image :class "window-icon" + :path "${w.icon}" + :image-width 20 + :image-height 20)))))) (defwidget system-widget [] - (box :orientation "v" :space-evenly false :spacing 6 :halign "fill" :class "system" - (box :orientation "v" :class "system-item" :halign "fill" :space-evenly false :spacing 4 + (box :orientation "v" + :space-evenly false + :spacing 6 + :halign "fill" + :class "system" + (box :orientation "v" + :class "system-item" + :halign "fill" + :space-evenly false + :spacing 4 :tooltip "${system_stats.net.tooltip}" (image :class "system-icon" :path "${system_stats.net.status == 'down' ? '@@icon-offline@@' : system_stats.net.routes[0].type == 'wifi' ? '@@icon-wifi@@' : system_stats.net.routes[0].type == 'ethernet' ? '@@icon-ethernet@@' : system_stats.net.routes[0].type == 'tun' ? '@@icon-proxy@@' : '@@icon-offline@@'}" - :image-width 24 :image-height 24) + :image-width 24 + :image-height 24) (label :class "system-label small" :text "${system_stats.net.status == 'down' ? '-' : system_stats.net.routes[0].tx}") (label :class "system-label small" :text "${system_stats.net.status == 'down' ? '-' : system_stats.net.routes[0].rx}")) - (box :orientation "v" :class "system-item" :space-evenly false :spacing 4 + (box :orientation "v" + :class "system-item" + :space-evenly false + :spacing 4 :tooltip "${system_stats.cpu.tooltip}" - (image :class "system-icon" :path "@@icon-cpu@@" :image-width 24 :image-height 24) + (image :class "system-icon" + :path "@@icon-cpu@@" + :image-width 24 + :image-height 24) (label :class "system-label" :text "${system_stats.cpu.percent}%")) - (box :orientation "v" :class "system-item" :space-evenly false :spacing 4 + (box :orientation "v" + :class "system-item" + :space-evenly false + :spacing 4 :tooltip "${system_stats.ram.tooltip}" - (image :class "system-icon" :path "@@icon-ram@@" :image-width 24 :image-height 24) + (image :class "system-icon" + :path "@@icon-ram@@" + :image-width 24 + :image-height 24) (label :class "system-label" :text "${system_stats.ram.percent}%")) - (box :orientation "v" :class "system-item" :space-evenly false :spacing 4 + (box :orientation "v" + :class "system-item" + :space-evenly false + :spacing 4 :tooltip "${system_stats.battery.tooltip}" - (image :class "system-icon" :path "@@icon-battery@@" :image-width 24 :image-height 24) - (label :class "system-label" :text "${system_stats.battery.present ? (system_stats.battery.percent + '%') : '-'}")) + (image :class "system-icon" + :path "@@icon-battery@@" + :image-width 24 + :image-height 24) + (label :class "system-label" + :text "${system_stats.battery.present ? (system_stats.battery.percent + '%') : '-'}")) (eventbox :onclick "pamixer --toggle-mute" :onscroll "bash -c '[ \"{}\" = \"up\" ] && pamixer --increase 5 --unmute || pamixer --decrease 5'" - :cursor "pointer" :halign "fill" - (box :orientation "v" :space-evenly false :spacing 4 :class "system-item" + :cursor "pointer" + :halign "fill" + (box :orientation "v" + :space-evenly false + :spacing 4 + :class "system-item" :tooltip "${system_stats.sound.tooltip}" - (image :class "system-icon" :path "@@icon-audio@@" :image-width 24 :image-height 24) - (label :class "system-label" :text "${system_stats.sound.mute ? '-' : (system_stats.sound.percent + '%')}"))) - (box :orientation "v" :class "system-item" :space-evenly false :spacing 4 + (image :class "system-icon" + :path "@@icon-audio@@" + :image-width 24 + :image-height 24) + (label :class "system-label" + :text "${system_stats.sound.mute ? '-' : (system_stats.sound.percent + '%')}"))) + (box :orientation "v" + :class "system-item" + :space-evenly false + :spacing 4 :tooltip "${full_date} ${time} (${date})" - (image :class "system-icon" :path "@@icon-calendar@@" :image-width 24 :image-height 24) + (image :class "system-icon" + :path "@@icon-calendar@@" + :image-width 24 + :image-height 24) (label :class "system-label small" :text time) (label :class "system-label small" :text ampm) (label :class "system-label small" :text date)))) diff --git a/modules/desktop/eww/bar/system-stats.lua b/modules/desktop/eww/bar/system-stats.lua index bc9cc90..9571d26 100644 --- a/modules/desktop/eww/bar/system-stats.lua +++ b/modules/desktop/eww/bar/system-stats.lua @@ -4,6 +4,7 @@ -- Single-threaded LuaJIT port of the original Python script. Instead of -- OS threads, a single supervisor loop schedules the periodic cpu/ram and -- sound refreshes and polls an inotifywait child for link-state changes. + local cjson = require("cjson") local posix = require("posix") local unistd = require("posix.unistd") @@ -23,13 +24,13 @@ end local net_last_time = nil local net_last_bytes = {} --- ------------------------------------------------ time +-- TIME local function mono_sec() local g = gettimeofday() return g.tv_sec + g.tv_usec / 1e6 end --- ------------------------------------------------ process helpers +-- PROCESS HELPERS local function sh(cmd) local h = io.popen(cmd) if not h then @@ -40,7 +41,7 @@ local function sh(cmd) return out end --- ------------------------------------------------ formatting +-- FORMATTING local function format_rate(bytes_per_sec) if bytes_per_sec == nil or bytes_per_sec < 0 then return "0B" @@ -77,7 +78,7 @@ local function format_bytes(kib) return string.format("%.1f%s", val, unit) end --- ------------------------------------------------ /proc readers +-- /proc READERS local function read_cpu_times() local times = {} local f = io.open("/proc/stat") @@ -192,7 +193,7 @@ local function get_ram_speed_mhz() return mx end --- ------------------------------------------------ network helpers +-- NETWORK HELPERS local function get_all_default_ifaces() local out = sh("ip -o route show default 2>/dev/null") if not out then @@ -305,7 +306,7 @@ local function get_iface_io_bytes(iface) return rx, tx end --- ------------------------------------------------ tooltips +-- TOOLTIPS local function build_cpu_tooltip(overall_pct, per_core_list, freq_mhz, load_avg) local lines = { string.format("CPU: %d%%", overall_pct) } if freq_mhz ~= nil then @@ -337,7 +338,7 @@ local function build_ram_tooltip(ram_pct, used, total, available, swap_pct, swap return table.concat(lines, "\n") end --- ------------------------------------------------ state collectors +-- STATE COLLECTORS -- get_all_default_ifaces (`ip route`), get_iface_ip (`ip addr`), and the -- wifi branch of get_speed_mbps (`iw dev link`) each spawn a subprocess. -- Those three rarely change second-to-second, so they're only re-probed @@ -530,7 +531,7 @@ local function get_sound_state() } end --- ------------------------------------------------ battery +-- BATTERY local function find_battery_path() local handle = io.popen("ls /sys/class/power_supply/ 2>/dev/null") if not handle then @@ -608,7 +609,7 @@ end local battery_path = find_battery_path() --- ------------------------------------------------ state + emit +-- state + emit local state = { cpu = { percent = 0, @@ -657,7 +658,7 @@ local CPU_INTERVAL = 2.0 local SOUND_INTERVAL = 1.0 local INOTIFY_RETRY_INTERVAL = 30.0 -- backoff between (re)spawn attempts --- ------------------------------------------------ inotifywait child +-- inotifywait child -- Returns pid, read_fd on success, or nil, nil if the fork/exec setup -- itself failed outright (pipe/fork syscall failure, not inotifywait -- failing later). @@ -694,7 +695,7 @@ local function spawn_inotify() return pid, r end --- ------------------------------------------------ main loop +-- MAIN LOOP local function main() local ram_speed_mhz = get_ram_speed_mhz() @@ -878,7 +879,7 @@ local function main() -- Empty read on a "ready" fd means the write end closed, i.e. -- the inotifywait child exited (crashed, watched path missing, -- binary not found, etc). Reap it, drop the fd, and don't - -- touch it again until the next backed-off retry -- this is + -- touch it again until the next backed-off retry; this is -- the fix for the tight busy-loop: without this branch, poll() -- would report this dead fd as "ready" forever, on every -- single iteration, with an effectively-zero timeout. diff --git a/modules/desktop/eww/default.nix b/modules/desktop/eww/default.nix index dfc80cd..be6236f 100644 --- a/modules/desktop/eww/default.nix +++ b/modules/desktop/eww/default.nix @@ -1,8 +1,13 @@ +# ElKowar's Wacky Widgets — desktop widgets and bar { config, lib, + pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { imports = [ ./bar/bar.nix @@ -22,38 +27,35 @@ enable = true; systemd = { enable = true; - # Nothing ever activates this, so home-manager's eww.service unit - # exists but is never auto-started by the session. Rely on eww-bar.service - # manually starts eww service. + # Nothing auto-starts home-manager's eww.service unit; the eww-bar + # service below starts the daemon on demand. target = "eww-daemon-manual.target"; }; scssConfig = let - baseSize = config.fonts.size; + themedStyleSheet = + builtins.replaceStrings + [ + "@@font-family@@" + "@@font-size@@" + "@@font-size-icon@@" + "@@font-size-label@@" + "@@font-size-small@@" + "@@font-size-idx@@" + ] + [ + config.fonts.normal + (toString config.fonts.size) + (toString config.fonts.iconSize) + (toString config.fonts.labelSize) + (toString config.fonts.smallSize) + (toString config.fonts.idxSize) + ] + (builtins.readFile ./eww.scss); in - builtins.readFile ( - config.scheme { - template = - builtins.replaceStrings - [ - "@@font-family@@" - "@@font-size@@" - "@@font-size-icon@@" - "@@font-size-label@@" - "@@font-size-small@@" - "@@font-size-idx@@" - ] - [ - config.fonts.normal - (toString baseSize) - (toString config.fonts.iconSize) - (toString config.fonts.labelSize) - (toString config.fonts.smallSize) - (toString config.fonts.idxSize) - ] - (builtins.readFile ./eww.scss); - } - ); + builtins.readFile (base16Colors { + templateFileOrContent = themedStyleSheet; + }); }; systemd.user.services.eww-bar = { diff --git a/modules/desktop/niri/default.nix b/modules/desktop/niri/default.nix index b13cdf4..9b0b160 100644 --- a/modules/desktop/niri/default.nix +++ b/modules/desktop/niri/default.nix @@ -1,9 +1,13 @@ +# Niri scrollable-tiling Wayland compositor and desktop essentials { config, lib, pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { imports = [ ./keybindings.nix ]; @@ -64,7 +68,7 @@ x11.enable = true; }; - wayland.windowManager.niri.settings = { + wayland.windowManager.niri.settings = with base16Colors.colorsWithHashPrefix; { hotkey-overlay = { skip-at-startup = { }; }; @@ -94,8 +98,8 @@ background-color = "transparent"; focus-ring = { width = 1; - active-color = config.scheme.withHashtag.base07; - inactive-color = config.scheme.withHashtag.base03; + active-color = base07; + inactive-color = base03; }; border.off = { }; shadow.off = { }; diff --git a/modules/desktop/rofi/default.nix b/modules/desktop/rofi/default.nix index ced9167..bbf1aea 100644 --- a/modules/desktop/rofi/default.nix +++ b/modules/desktop/rofi/default.nix @@ -1,8 +1,13 @@ +# Application launcher and dmenu replacement { config, lib, + pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { options.desktop.rofi = { package = lib.mkOption { @@ -18,7 +23,7 @@ enable = true; theme = let - template = + fontExpandedThemeTemplate = builtins.replaceStrings [ "@@rofi-font@@" @@ -30,9 +35,9 @@ ] (builtins.readFile ./theme.rasi); in - "${config.scheme { - inherit template; - extension = ".rasi"; + "${base16Colors { + templateFileOrContent = fontExpandedThemeTemplate; + fileExtension = ".rasi"; }}"; extraConfig = { modi = "drun"; diff --git a/modules/desktop/xdg/default.nix b/modules/desktop/xdg/default.nix index ef27182..7f46d37 100644 --- a/modules/desktop/xdg/default.nix +++ b/modules/desktop/xdg/default.nix @@ -5,6 +5,9 @@ pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { config = lib.mkIf config.desktop.enable { dconf.enable = true; @@ -25,12 +28,10 @@ gtk = let - gtkCss = builtins.readFile ( - config.scheme { - template = builtins.readFile ./style.css; - extension = ".css"; - } - ); + gtkColorSchemeCss = builtins.readFile (base16Colors { + templateFileOrContent = builtins.readFile ./style.css; + fileExtension = ".css"; + }); in { enable = true; @@ -52,12 +53,12 @@ size = 20; }; colorScheme = "dark"; - gtk3.extraCss = gtkCss; + gtk3.extraCss = gtkColorSchemeCss; gtk4 = { # GTK 4/libadwaita does not support loading GTK 3 themes; use the - # OneDark Dark CSS above without Home Manager's compatibility workaround. + # themed CSS above without Home Manager's compatibility workaround. theme = null; - extraCss = gtkCss; + extraCss = gtkColorSchemeCss; }; }; }; diff --git a/modules/development/lazygit/default.nix b/modules/development/lazygit/default.nix index eb4c739..1e83ed0 100644 --- a/modules/development/lazygit/default.nix +++ b/modules/development/lazygit/default.nix @@ -1,5 +1,13 @@ # A simple terminal UI for git commands -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { imports = [ ./assertions.nix @@ -35,7 +43,7 @@ enableBashIntegration = false; enableZshIntegration = config.terminal.zsh.enable; settings = { - gui = with config.scheme.withHashtag; { + gui = with base16Colors.colorsWithHashPrefix; { theme = { lightTheme = false; activeBorderColor = [ diff --git a/modules/development/nixvim/colorscheme.nix b/modules/development/nixvim/colorscheme.nix index 3ab5bc4..560f6ce 100644 --- a/modules/development/nixvim/colorscheme.nix +++ b/modules/development/nixvim/colorscheme.nix @@ -2,30 +2,17 @@ { config, lib, + pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { config.programs.nixvim = lib.mkIf config.development.nixvim.enable { colorschemes.base16 = { enable = true; - colorscheme = with config.scheme.withHashtag; { - base00 = base00; - base01 = base01; - base02 = base02; - base03 = base03; - base04 = base04; - base05 = base05; - base06 = base06; - base07 = base07; - base08 = base08; - base09 = base09; - base0A = base0A; - base0B = base0B; - base0C = base0C; - base0D = base0D; - base0E = base0E; - base0F = base0F; - }; + colorscheme = base16Colors.colorsWithHashPrefix; }; }; } diff --git a/modules/development/nixvim/default.nix b/modules/development/nixvim/default.nix index 8506b7d..74b0c1f 100644 --- a/modules/development/nixvim/default.nix +++ b/modules/development/nixvim/default.nix @@ -1,5 +1,13 @@ # Neovim configured through Nix -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { imports = [ ./colorscheme.nix @@ -44,7 +52,7 @@ globals.mapleader = " "; clipboard.providers.xclip.enable = true; - highlight = with config.scheme.withHashtag; { + highlight = with base16Colors.colorsWithHashPrefix; { WinSeparator = { fg = base01; bg = base00; diff --git a/modules/development/nixvim/plugins/gitsigns.nix b/modules/development/nixvim/plugins/gitsigns.nix index 28123fd..d9bda21 100644 --- a/modules/development/nixvim/plugins/gitsigns.nix +++ b/modules/development/nixvim/plugins/gitsigns.nix @@ -1,5 +1,13 @@ # Git integration: signs, blame, diffs and hunk operations -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: +let + base16Colors = import ../../../colors/base16 { inherit config lib pkgs; }; +in { config.programs.nixvim = lib.mkIf config.development.nixvim.enable { plugins.gitsigns = { @@ -91,7 +99,7 @@ }; }; - highlight = with config.scheme.withHashtag; { + highlight = with base16Colors.colorsWithHashPrefix; { GitSignsAdd.fg = base0B; GitSignsChange.fg = base0A; GitSignsDelete.fg = base08; diff --git a/modules/development/nixvim/plugins/lualine.nix b/modules/development/nixvim/plugins/lualine.nix index 560a055..55326ee 100644 --- a/modules/development/nixvim/plugins/lualine.nix +++ b/modules/development/nixvim/plugins/lualine.nix @@ -1,11 +1,19 @@ # Statusline configuration -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: +let + base16Colors = import ../../../colors/base16 { inherit config lib pkgs; }; +in { config.programs.nixvim.plugins.lualine = lib.mkIf config.development.nixvim.enable { enable = true; settings = { options = { - theme = with config.scheme.withHashtag; { + theme = with base16Colors.colorsWithHashPrefix; { normal = { a = { fg = base00; diff --git a/modules/file-management/yazi/theme.nix b/modules/file-management/yazi/theme.nix index e960d84..6589200 100644 --- a/modules/file-management/yazi/theme.nix +++ b/modules/file-management/yazi/theme.nix @@ -1,7 +1,16 @@ -{ config, lib, ... }: +# Yazi theme derived from the shared base16 color scheme +{ + config, + lib, + pkgs, + ... +}: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { config = lib.mkIf config.file-management.yazi.enable { - programs.yazi.theme = with config.scheme.withHashtag; { + programs.yazi.theme = with base16Colors.colorsWithHashPrefix; { manager = { cwd = { fg = base0D; diff --git a/modules/system/nix-update/nix-update.sh b/modules/system/nix-update/nix-update.sh index e65a33c..79718fd 100644 --- a/modules/system/nix-update/nix-update.sh +++ b/modules/system/nix-update/nix-update.sh @@ -8,13 +8,13 @@ warn() { printf '\033[1;33m==> warning:\033[0m %s\n' "$*" >&2; } error() { printf '\033[1;31m==> error:\033[0m %s\n' "$*" >&2; } die() { error "$*"; exit 1; } -HM_DIR="$HOME/.config/home-manager" -NIXOS_DIR="/etc/nixos" -ONLY_FLAKE=false -ONLY_SWITCH=false -TARGET="" +HOME_MANAGER_CONFIG_DIR="$HOME/.config/home-manager" +NIXOS_CONFIG_DIR="/etc/nixos" +ONLY_UPDATE_FLAKE_INPUTS=false +ONLY_SWITCH_CONFIGURATION=false +UPDATE_TARGET="" -usage() { +print_usage() { echo "Usage: $0 <home-manager|nixos|both> [--only-flake|--only-switch]" echo "" echo "Commands:" @@ -28,58 +28,58 @@ usage() { exit 1 } -parse_args() { +parse_command_line_arguments() { while [[ $# -gt 0 ]]; do case "$1" in home-manager | nixos | both) - if [[ -n "$TARGET" ]]; then + if [[ -n "$UPDATE_TARGET" ]]; then error "only one target allowed" - usage + print_usage fi - TARGET="$1" + UPDATE_TARGET="$1" shift ;; --only-flake) - ONLY_FLAKE=true + ONLY_UPDATE_FLAKE_INPUTS=true shift ;; --only-switch) - ONLY_SWITCH=true + ONLY_SWITCH_CONFIGURATION=true shift ;; -h | --help) - usage + print_usage ;; *) error "unknown option '$1'" - usage + print_usage ;; esac done - if [[ -z "$TARGET" ]]; then + if [[ -z "$UPDATE_TARGET" ]]; then error "no target specified" - usage + print_usage fi } -update_home_manager() { +update_home_manager_configuration() { info "Updating home-manager..." - cd "$HM_DIR" + cd "$HOME_MANAGER_CONFIG_DIR" info "Staging users/arpit/private.nix..." git add users/arpit/private.nix -f trap 'git rm --cached users/arpit/private.nix >/dev/null 2>&1 || true' EXIT INT TERM HUP - if [[ "$ONLY_SWITCH" == false ]]; then + if [[ "$ONLY_SWITCH_CONFIGURATION" == false ]]; then info "Running nix flake update..." nix flake update fi - if [[ "$ONLY_FLAKE" == false ]]; then + if [[ "$ONLY_UPDATE_FLAKE_INPUTS" == false ]]; then info "Running home-manager switch..." - home-manager switch --flake "$HM_DIR#arpit" + home-manager switch --flake "$HOME_MANAGER_CONFIG_DIR#arpit" fi info "Unstaging users/arpit/private.nix..." @@ -90,22 +90,22 @@ update_home_manager() { info "home-manager update complete" } -update_nixos() { +update_nixos_configuration() { info "Updating NixOS..." sudo -v - cd "$NIXOS_DIR" + cd "$NIXOS_CONFIG_DIR" info "Staging hardware-configuration.nix..." git add hardware-configuration.nix -f trap 'git rm --cached hardware-configuration.nix >/dev/null 2>&1 || true' EXIT INT TERM HUP - if [[ "$ONLY_SWITCH" == false ]]; then + if [[ "$ONLY_SWITCH_CONFIGURATION" == false ]]; then info "Running nix flake update..." nix flake update fi - if [[ "$ONLY_FLAKE" == false ]]; then + if [[ "$ONLY_UPDATE_FLAKE_INPUTS" == false ]]; then info "Running nixos-rebuild switch..." sudo nixos-rebuild switch fi @@ -118,17 +118,17 @@ update_nixos() { info "NixOS update complete" } -parse_args "$@" +parse_command_line_arguments "$@" -case "$TARGET" in +case "$UPDATE_TARGET" in home-manager) - update_home_manager + update_home_manager_configuration ;; nixos) - update_nixos + update_nixos_configuration ;; both) - update_nixos - update_home_manager + update_nixos_configuration + update_home_manager_configuration ;; esac diff --git a/modules/terminal/bat/default.nix b/modules/terminal/bat/default.nix index 8e089ce..69045bc 100644 --- a/modules/terminal/bat/default.nix +++ b/modules/terminal/bat/default.nix @@ -5,6 +5,9 @@ pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { options.terminal.bat = { enable = lib.mkEnableOption "Enables bat."; @@ -26,7 +29,7 @@ base16 = { src = pkgs.runCommand "bat-base16-theme" { } '' mkdir -p $out - cp ${config.scheme { template = ./base16.tmTheme; }} $out/base16.tmTheme + cp ${base16Colors { templateFileOrContent = ./base16.tmTheme; }} $out/base16.tmTheme ''; file = "base16.tmTheme"; }; diff --git a/modules/terminal/fzf/default.nix b/modules/terminal/fzf/default.nix index 613134e..a7cc2f5 100644 --- a/modules/terminal/fzf/default.nix +++ b/modules/terminal/fzf/default.nix @@ -2,8 +2,12 @@ { config, lib, + pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { imports = [ ./assertions.nix ]; @@ -39,7 +43,7 @@ "--margin='1,2'" ]; - colors = with config.scheme.withHashtag; { + colors = with base16Colors.colorsWithHashPrefix; { fg = base05; bg = "-1"; hl = base0D; diff --git a/modules/terminal/kitty/default.nix b/modules/terminal/kitty/default.nix index 0e293bd..d840667 100644 --- a/modules/terminal/kitty/default.nix +++ b/modules/terminal/kitty/default.nix @@ -2,8 +2,12 @@ { config, lib, + pkgs, ... }: +let + base16Colors = import ../../colors/base16 { inherit config lib pkgs; }; +in { options.terminal.kitty = { enable = lib.mkEnableOption "Enables kitty."; @@ -41,7 +45,7 @@ map ctrl+shift+u scroll_page_up map ctrl+shift+d scroll_page_down ''; - settings = with config.scheme.withHashtag; { + settings = with base16Colors.colorsWithHashPrefix; { window_padding_width = 10; font_size = config.fonts.size; font_family = config.fonts.normal; diff --git a/modules/web/chromium/extensions/default.nix b/modules/web/chromium/extensions/default.nix index 1b457c8..a7b1e91 100644 --- a/modules/web/chromium/extensions/default.nix +++ b/modules/web/chromium/extensions/default.nix @@ -5,8 +5,6 @@ ... }: let - cfg = config.web.chromium; - extLib = import ./lib.nix { inherit lib pkgs config; }; diff --git a/modules/web/chromium/extensions/inject_extension_key.lua b/modules/web/chromium/extensions/inject_extension_key.lua index 41c631d..f5c8c2b 100644 --- a/modules/web/chromium/extensions/inject_extension_key.lua +++ b/modules/web/chromium/extensions/inject_extension_key.lua @@ -3,70 +3,76 @@ -- extension's public key, and rewrite it. local dkjson = require("dkjson") -local manifest_path = assert(arg[1], "usage: inject_extension_key.lua <manifest> <ext_key>") -local ext_key = assert(arg[2], "usage: inject_extension_key.lua <manifest> <ext_key>") +local manifest_path = assert(arg[1], "usage: inject_extension_key.lua <manifest> <extension_key>") +local extension_key = assert(arg[2], "usage: inject_extension_key.lua <manifest> <extension_key>") -local f = assert(io.open(manifest_path, "r")) -local content = f:read("*a") -f:close() +local manifest_file = assert(io.open(manifest_path, "r")) +local manifest_content = manifest_file:read("*a") +manifest_file:close() -- Hand-rolled scanner that removes // and /* */ comments and mid-JSON -- trailing commas while respecting string literals (including escapes). -local sb = {} -local i, n = 1, #content -local in_string = false +local sanitized_chunks = {} +local character_position = 1 +local content_length = #manifest_content +local inside_string_literal = false local function trim_trailing_comma() - while #sb > 0 and (sb[#sb] == " " or sb[#sb] == "\t" or sb[#sb] == "\n" or sb[#sb] == "\r") do - sb[#sb] = nil + while #sanitized_chunks > 0 do + local last_chunk = sanitized_chunks[#sanitized_chunks] + if last_chunk ~= " " and last_chunk ~= "\t" and last_chunk ~= "\n" and last_chunk ~= "\r" then + break + end + sanitized_chunks[#sanitized_chunks] = nil end - if #sb > 0 and sb[#sb] == "," then - sb[#sb] = nil + if #sanitized_chunks > 0 and sanitized_chunks[#sanitized_chunks] == "," then + sanitized_chunks[#sanitized_chunks] = nil end end -while i <= n do - local c = content:sub(i, i) - if in_string then - sb[#sb + 1] = c - if c == "\\" and i < n then - sb[#sb + 1] = content:sub(i + 1, i + 1) - i = i + 2 +while character_position <= content_length do + local current_character = manifest_content:sub(character_position, character_position) + if inside_string_literal then + sanitized_chunks[#sanitized_chunks + 1] = current_character + if current_character == "\\" and character_position < content_length then + -- Preserve escaped characters verbatim so escape sequences are not split. + sanitized_chunks[#sanitized_chunks + 1] = manifest_content:sub(character_position + 1, character_position + 1) + character_position = character_position + 2 else - if c == '"' then - in_string = false + if current_character == '"' then + inside_string_literal = false end - i = i + 1 + character_position = character_position + 1 end else - local two = content:sub(i, i + 1) - if c == '"' then - in_string = true - sb[#sb + 1] = c - i = i + 1 - elseif two == "//" then - local nl = content:find("\n", i) or (n + 1) - i = nl - elseif two == "/*" then - local close = content:find("%*/", i + 2) - if not close then + local character_pair = manifest_content:sub(character_position, character_position + 1) + if current_character == '"' then + inside_string_literal = true + sanitized_chunks[#sanitized_chunks + 1] = current_character + character_position = character_position + 1 + elseif character_pair == "//" then + local line_end_position = manifest_content:find("\n", character_position) or (content_length + 1) + character_position = line_end_position + elseif character_pair == "/*" then + local comment_end_position = manifest_content:find("%*/", character_position + 2) + if not comment_end_position then break end - i = close + 2 - elseif c == "]" or c == "}" then + character_position = comment_end_position + 2 + elseif current_character == "]" or current_character == "}" then trim_trailing_comma() - sb[#sb + 1] = c - i = i + 1 + sanitized_chunks[#sanitized_chunks + 1] = current_character + character_position = character_position + 1 else - sb[#sb + 1] = c - i = i + 1 + sanitized_chunks[#sanitized_chunks + 1] = current_character + character_position = character_position + 1 end end end -local data = dkjson.decode(table.concat(sb)) -data.key = ext_key +local manifest_data = dkjson.decode(table.concat(sanitized_chunks)) +manifest_data.key = extension_key -f = assert(io.open(manifest_path, "w")) -f:write(dkjson.encode(data, { indent = true })) -f:close() +manifest_file = assert(io.open(manifest_path, "w")) +manifest_file:write(dkjson.encode(manifest_data, { indent = true })) +manifest_file:close() diff --git a/modules/web/chromium/extensions/lib.nix b/modules/web/chromium/extensions/lib.nix index 11ec204..7059b35 100644 --- a/modules/web/chromium/extensions/lib.nix +++ b/modules/web/chromium/extensions/lib.nix @@ -21,10 +21,13 @@ nativeBuildInputs = [ config.file-management.ouch.package + # TODO: Switch to using cjson. As we are already using it for other + # scripts like eww (pkgs.luajit.withPackages (ps: [ ps.dkjson ])) ]; dontUnpack = true; + # TODO: Move this into its own file buildPhase = '' runHook preBuild mkdir -p $out diff --git a/users/arpit/default.nix b/users/arpit/default.nix index 0448d13..7e35156 100644 --- a/users/arpit/default.nix +++ b/users/arpit/default.nix @@ -11,6 +11,9 @@ home.homeDirectory = "/home/${config.home.username}"; home.stateVersion = "25.05"; + # Configuration wide colorscheme to use + colors.base16 = "onedark-dark"; + # Desktop environment desktop.enable = true; desktop.hardware.gpu = { @@ -18,8 +21,6 @@ amd.enable = true; }; - colors.onedark-dark.enable = true; - # Gaming gaming.heroic.enable = true; gaming.steam.enable = false; |
