From 4124a5ae231a585b945c9547a3ab0c37a4eba7e3 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar Date: Sat, 18 Jul 2026 12:15:20 +0530 Subject: refactor: replace zsh deps with runtimeShell, migrate scripts from symlinkJoin to runCommand, add missing assertions and deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scripts: Migrated from symlinkJoin to runCommand; replaced zsh dependency with pkgs.runtimeShell across polybar, scripts, and fzf-launcher Assertions: Added gopass/gpg checks for neomutt, signing checks for git, git dependency for lazygit, file-preview deps for lf, desktop/kitten checks for scripts Lazygit: Fixed mkIf placement, imported assertions Neomutt: Removed verbose keybinding descriptions Nixvim: Removed notification-clear mapping File preview: Replaced libreoffice document preview with pandoc/antiword (terminal-based) Fzf launcher: Fixed bash compatibility (setopt → shopt -s) Deps: Added coreutils, fontconfig, antiword, pandoc, util-linux, bash, findutils, grep, sed, gawk, ncurses to various scripts --- modules/communication/neomutt/account/default.nix | 31 +++++++- modules/communication/neomutt/macros.nix | 6 -- modules/desktop/polybar/module/vpn-separator.nix | 2 +- modules/desktop/polybar/module/vpn.nix | 2 +- modules/development/git/assertions.nix | 22 ++++++ modules/development/lazygit/assertions.nix | 10 +++ modules/development/lazygit/default.nix | 7 +- modules/development/nixvim/keymaps.nix | 5 -- modules/file-management/lf/default.nix | 11 +++ modules/scripts/default.nix | 86 +++++++++++++++-------- modules/scripts/file-preview.sh | 21 +++--- modules/scripts/fzf-launcher.sh | 2 +- 12 files changed, 148 insertions(+), 57 deletions(-) create mode 100644 modules/development/lazygit/assertions.nix (limited to 'modules') diff --git a/modules/communication/neomutt/account/default.nix b/modules/communication/neomutt/account/default.nix index 0b75c9a..4d32ad7 100644 --- a/modules/communication/neomutt/account/default.nix +++ b/modules/communication/neomutt/account/default.nix @@ -20,7 +20,36 @@ in description = "Specification of email accounts."; }; - config = mkIf config.communication.neomutt.enable { + config = { + assertions = [ + { + assertion = + !config.communication.neomutt.enable + || !lib.any (account: account.enable && account.passwordGopassSecret != null) ( + lib.attrValues config.communication.neomutt.accounts + ) + || config.security.gopass.enable; + message = '' + An enabled communication.neomutt account uses passwordGopassSecret but security.gopass.enable is not set. + Enable security.gopass to provide the account password command. + ''; + } + { + assertion = + !config.communication.neomutt.enable + || !lib.any (account: account.enable && account.gpg.key != null) ( + lib.attrValues config.communication.neomutt.accounts + ) + || config.security.gpg.enable; + message = '' + An enabled communication.neomutt account specifies a GPG key but security.gpg.enable is not set. + Enable security.gpg to provide mail signing and encryption support. + ''; + } + ]; + + } + // mkIf config.communication.neomutt.enable { accounts.email.accounts = mapAttrs ( name: account: let diff --git a/modules/communication/neomutt/macros.nix b/modules/communication/neomutt/macros.nix index e65436c..0548a0f 100644 --- a/modules/communication/neomutt/macros.nix +++ b/modules/communication/neomutt/macros.nix @@ -9,7 +9,6 @@ ]; key = "O"; action = "set my_wait_key=$wait_key wait_key=no${lib.getExe config.scripts.neomutt-sync.package}set wait_key=$my_wait_key"; - description = "sync mailbox (run neomutt-sync)"; } { # gx: extract links from the current message and open one, vim-netrw style @@ -19,7 +18,6 @@ ]; key = "gx"; action = "urlscan"; - description = "extract links from message (netrw-style)"; } { map = [ @@ -28,7 +26,6 @@ ]; key = "gl"; action = "less ~/.config/neomutt/flag_legend.txt"; - description = "show flag legend"; } { # gF: clear the current limit/filter and show every message again, @@ -36,21 +33,18 @@ map = [ "index" ]; key = "gF"; action = "~A"; - description = "clear limit/filter, show all messages"; } { # ZZ: save and quit, vim-style (sync mailbox, then quit) map = [ "index" ]; key = "ZZ"; action = ""; - description = "save changes and quit"; } { # ZQ: quit without saving, vim-style counterpart to ZZ map = [ "index" ]; key = "ZQ"; action = ""; - description = "quit without saving"; } ]; } diff --git a/modules/desktop/polybar/module/vpn-separator.nix b/modules/desktop/polybar/module/vpn-separator.nix index 48122cd..2444522 100644 --- a/modules/desktop/polybar/module/vpn-separator.nix +++ b/modules/desktop/polybar/module/vpn-separator.nix @@ -7,7 +7,7 @@ with config.scheme.withHashtag; { type = "custom/script"; - exec-if = "${lib.getExe config.terminal.zsh.package} -c '${lib.getExe' pkgs.iproute2 "ip"} a | ${lib.getExe pkgs.gnugrep} -q tun0'"; + exec-if = "${pkgs.runtimeShell} -c '${lib.getExe' pkgs.iproute2 "ip"} a | ${lib.getExe pkgs.gnugrep} -q tun0'"; exec = "echo VPN"; interval = 5; diff --git a/modules/desktop/polybar/module/vpn.nix b/modules/desktop/polybar/module/vpn.nix index 6230b8d..58bb80c 100644 --- a/modules/desktop/polybar/module/vpn.nix +++ b/modules/desktop/polybar/module/vpn.nix @@ -7,7 +7,7 @@ with config.scheme.withHashtag; { type = "custom/script"; - exec-if = "${lib.getExe config.terminal.zsh.package} -c '${lib.getExe' pkgs.iproute2 "ip"} a | ${lib.getExe pkgs.gnugrep} -q tun0'"; + exec-if = "${pkgs.runtimeShell} -c '${lib.getExe' pkgs.iproute2 "ip"} a | ${lib.getExe pkgs.gnugrep} -q tun0'"; exec = "echo VPN"; interval = 5; diff --git a/modules/development/git/assertions.nix b/modules/development/git/assertions.nix index d663173..c18c847 100644 --- a/modules/development/git/assertions.nix +++ b/modules/development/git/assertions.nix @@ -10,5 +10,27 @@ SSH must be enabled (security.ssh.enable = true) to use SSH for git. ''; } + { + assertion = !config.development.git.signing.signByDefault || config.development.git.enable; + message = '' + development.git.signing.signByDefault is enabled but development.git.enable is not. + Enable development.git before enabling commit signing. + ''; + } + { + assertion = + !config.development.git.signing.signByDefault || config.development.git.signing.key != null; + message = '' + development.git.signing.signByDefault is enabled but development.git.signing.key is not set. + Set a GPG key ID before enabling commit signing by default. + ''; + } + { + assertion = !config.development.git.signing.signByDefault || config.security.gpg.enable; + message = '' + development.git.signing.signByDefault is enabled but security.gpg.enable is not. + Commit signing requires the managed GPG configuration. Please enable security.gpg. + ''; + } ]; } diff --git a/modules/development/lazygit/assertions.nix b/modules/development/lazygit/assertions.nix new file mode 100644 index 0000000..b79cfb4 --- /dev/null +++ b/modules/development/lazygit/assertions.nix @@ -0,0 +1,10 @@ +# Assertions - LazyGit only makes sense when Git is enabled +{ config, ... }: +{ + assertions = [ + { + assertion = !config.development.lazygit.enable || config.development.git.enable; + message = "development.lazygit.enable requires development.git.enable."; + } + ]; +} diff --git a/modules/development/lazygit/default.nix b/modules/development/lazygit/default.nix index 8f5585e..223392a 100644 --- a/modules/development/lazygit/default.nix +++ b/modules/development/lazygit/default.nix @@ -1,11 +1,14 @@ # Lazygit - A simple terminal UI for git commands { config, lib, ... }: { + imports = [ + ./assertions.nix + ]; options.development.lazygit = { enable = lib.mkEnableOption "Enables lazygit."; }; - config = lib.mkIf config.development.lazygit.enable { - programs.lazygit = { + config = { + programs.lazygit = lib.mkIf config.development.lazygit.enable { enable = true; enableBashIntegration = config.terminal.bash.enable; enableFishIntegration = config.programs.fish.enable; diff --git a/modules/development/nixvim/keymaps.nix b/modules/development/nixvim/keymaps.nix index 0ac71f5..88fa841 100644 --- a/modules/development/nixvim/keymaps.nix +++ b/modules/development/nixvim/keymaps.nix @@ -31,10 +31,5 @@ ]; options.desc = "Toggle file explorer"; } - { - key = ""; - action = "NotificationsClear"; - options.desc = "Clear notifications"; - } ]; } diff --git a/modules/file-management/lf/default.nix b/modules/file-management/lf/default.nix index b6cfa22..cd9ca5c 100644 --- a/modules/file-management/lf/default.nix +++ b/modules/file-management/lf/default.nix @@ -19,6 +19,17 @@ }; config = lib.mkIf config.file-management.lf.enable { + assertions = [ + { + assertion = config.scripts.file-preview.enable; + message = "file-management.lf.enable requires scripts.file-preview.enable for file previews."; + } + { + assertion = config.scripts.file-preview-clean.enable; + message = "file-management.lf.enable requires scripts.file-preview-clean.enable to clear kitty previews."; + } + ]; + xdg.mimeApps.defaultApplications = { "inode/directory" = "lf.desktop"; }; diff --git a/modules/scripts/default.nix b/modules/scripts/default.nix index ffde799..a2d9e1a 100644 --- a/modules/scripts/default.nix +++ b/modules/scripts/default.nix @@ -6,8 +6,7 @@ ... }: let - shell = - if config.terminal.zsh.enable then (lib.getExe config.terminal.zsh.package) else "/usr/bin/env sh"; + shell = pkgs.runtimeShell; mkScript = name: path: env: deps: @@ -24,16 +23,20 @@ let ''; }; in - pkgs.symlinkJoin { - name = name; - paths = [ wrappedScript ] ++ deps; - buildInputs = [ pkgs.makeWrapper ]; - postBuild = '' + pkgs.runCommand name + { + name = name; + nativeBuildInputs = [ pkgs.makeWrapper ]; + meta.mainProgram = name; + } + '' + mkdir -p $out/bin + cp ${wrappedScript}/bin/${name} $out/bin/${name} + chmod +x $out/bin/${name} + wrapProgram $out/bin/${name} \ --prefix PATH : ${lib.makeBinPath deps} ''; - meta.mainProgram = name; - }; # Script definitions: { path, env?, deps?, conditions? } # condition: attrset of { option (string path), value (expected value) } @@ -60,22 +63,26 @@ let config.terminal.bat.package config.media.ffmpeg.package config.file-management.ouch.package + pkgs.coreutils pkgs.file + pkgs.fontconfig pkgs.librsvg + pkgs.antiword + pkgs.pandoc pkgs.poppler-utils + pkgs.util-linux ]; conditions = [ { - option = "media.ffmpeg.enable"; + option = "terminal.kitty.enable"; value = true; } { - option = "file-management.ouch.enable"; + option = "media.ffmpeg.enable"; value = true; } { - # not a dependency - option = "office.zathura.enable"; + option = "file-management.ouch.enable"; value = true; } { @@ -101,26 +108,30 @@ let deps = [ config.terminal.fzf.package pkgs.util-linux - config.terminal.zsh.package ]; conditions = [ { option = "terminal.fzf.enable"; value = true; } - { - option = "terminal.zsh.enable"; - value = true; - } ]; }; i3-keybindings = { path = ./i3-keybindings.sh; + deps = [ + pkgs.coreutils + pkgs.gawk + pkgs.ncurses + ]; conditions = [ { option = "desktop.enable"; value = true; } + { + option = "terminal.less.enable"; + value = true; + } ]; }; screen-recording = { @@ -147,6 +158,7 @@ let config.system.nvtop.package config.terminal.tmux.package config.terminal.kitty.package + pkgs.bash ]; conditions = [ { @@ -175,6 +187,10 @@ let deps = [ config.terminal.fzf.package config.security.openvpn.package + pkgs.coreutils + pkgs.findutils + pkgs.gnugrep + pkgs.gnused ]; conditions = [ { @@ -200,6 +216,10 @@ let path = ./neomutt-sync.sh; deps = [ pkgs.dialog + pkgs.coreutils + pkgs.gawk + pkgs.gnused + pkgs.util-linux config.programs.mbsync.package config.programs.notmuch.package ]; @@ -299,17 +319,25 @@ in }; }; - assertions = lib.concatLists ( - lib.mapAttrsToList ( - name: def: - map (cond: { - assertion = - !config.scripts.${name}.enable - || lib.attrByPath (lib.splitString "." cond.option) false config == cond.value; - message = "scripts.${name} is enabled but requires `${cond.option} = ${builtins.toJSON cond.value}`."; - }) (def.conditions or [ ]) - ) scriptDefs - ); + assertions = + lib.concatLists ( + lib.mapAttrsToList ( + name: def: + map (cond: { + assertion = + !config.scripts.${name}.enable + || lib.attrByPath (lib.splitString "." cond.option) false config == cond.value; + message = "scripts.${name} is enabled but requires `${cond.option} = ${builtins.toJSON cond.value}`."; + }) (def.conditions or [ ]) + ) scriptDefs + ) + ++ lib.mapAttrsToList (name: _: { + assertion = + !config.scripts.${name}.enable + || !config.scripts.${name}.desktop.enable + || config.terminal.kitty.enable; + message = "scripts.${name}.desktop.enable requires terminal.kitty.enable because desktop entries launch scripts in kitty."; + }) scriptDefs; home.packages = [ pkgs.file diff --git a/modules/scripts/file-preview.sh b/modules/scripts/file-preview.sh index fc07fe1..047252d 100644 --- a/modules/scripts/file-preview.sh +++ b/modules/scripts/file-preview.sh @@ -99,17 +99,16 @@ case "$MIMETYPE" in [ -s "$TMP_IMG" ] && render_image "$TMP_IMG" ;; - # --- OFFICE --- - application/vnd.openxmlformats-officedocument.*|application/msword|application/vnd.oasis.opendocument.*) - TMP_IMG="$TMP_DIR/doc-${INODE}.png" - if [ ! -f "$TMP_IMG" ]; then - libreoffice --headless --convert-to pdf --outdir "$TMP_DIR" "$FILE_PATH" >/dev/null 2>&1 - PDF_VER="${TMP_DIR}/$(basename "${FILE_PATH%.*}").pdf" - if [ -f "$PDF_VER" ]; then - pdftoppm -f 1 -l 1 -png -singlefile "$PDF_VER" "${TMP_IMG%.png}" >/dev/null 2>&1 - fi - fi - render_image "$TMP_IMG" + # --- OFFICE DOCUMENTS --- + # Extract text in the terminal instead of pulling in a graphical office suite. + application/vnd.openxmlformats-officedocument.wordprocessingml.document|application/vnd.oasis.opendocument.text) + pandoc --to plain "$FILE_PATH" 2>/dev/null + exit 0 + ;; + + application/msword) + antiword "$FILE_PATH" 2>/dev/null + exit 0 ;; # --- ARCHIVES --- diff --git a/modules/scripts/fzf-launcher.sh b/modules/scripts/fzf-launcher.sh index 1d7f968..5ae3d95 100644 --- a/modules/scripts/fzf-launcher.sh +++ b/modules/scripts/fzf-launcher.sh @@ -10,7 +10,7 @@ entries="" for dir in "${DIRS[@]}"; do [[ -d "$dir" ]] || continue - setopt nullglob + shopt -s nullglob for f in "$dir"/*.desktop; do [[ -f "$f" ]] || continue -- cgit v1.2.3