From d00b16c51115e41b00e0bf4a1ec3b539b8a91c6a Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Mon, 18 May 2026 15:28:15 -0500 Subject: [PATCH] zsh: escape cdpath entries Zsh cdpath is an array. Rendering entries by joining on spaces breaks paths containing spaces, glob characters, or other shell syntax. Use the shared shell array formatter so each configured cdpath entry is emitted as a quoted array element. --- modules/programs/zsh/default.nix | 5 ++++- tests/modules/programs/zsh/zshrc-content-priorities.nix | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/programs/zsh/default.nix b/modules/programs/zsh/default.nix index b148367e0..34d519946 100644 --- a/modules/programs/zsh/default.nix +++ b/modules/programs/zsh/default.nix @@ -398,6 +398,9 @@ in dirHashesStr = concatStringsSep "\n" ( lib.mapAttrsToList (k: v: ''hash -d ${k}="${v}"'') cfg.dirHashes ); + # Keep double quotes so existing configs using shell variables like + # $HOME still expand, while escaping chars special inside them. + cdpathStr = concatStringsSep " " (map (v: ''"${lib.escape [ "\\" "\"" "`" ] v}"'') cfg.cdpath); in mkIf cfg.enable ( lib.mkMerge [ @@ -520,7 +523,7 @@ in (lib.mkIf (cfg.cdpath != [ ]) ( mkOrder 510 '' - cdpath+=(${concatStringsSep " " cfg.cdpath}) + cdpath+=(${cdpathStr}) '' )) diff --git a/tests/modules/programs/zsh/zshrc-content-priorities.nix b/tests/modules/programs/zsh/zshrc-content-priorities.nix index 39d22f2ab..114c7e3f5 100644 --- a/tests/modules/programs/zsh/zshrc-content-priorities.nix +++ b/tests/modules/programs/zsh/zshrc-content-priorities.nix @@ -3,6 +3,12 @@ programs.zsh = { enable = true; + cdpath = [ + "$HOME/projects" + "/tmp/with space" + "/tmp/with[glob]" + ]; + initContent = lib.mkMerge [ (lib.mkBefore '' # High priority (mkBefore) @@ -34,6 +40,8 @@ echo "High priority content" typeset -U path cdpath fpath manpath + cdpath+=("$HOME/projects" "/tmp/with space" "/tmp/with[glob]") + for profile in ''${(z)NIX_PROFILES}; do fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) done