mirror of
https://github.com/nix-community/home-manager.git
synced 2025-03-20 23:30:07 +00:00
zsh: refactor zsh configuration for better order control over .zshrc
(#6479)
* zsh: add initContent option for custom .zshrc content insertion - Users can add content anywhere by using `lib.mkOrder`, `lib.mkBefore` and `lib.mkAfter` custom configurations. - Add test cases to verify the insertion of content before and after existing configurations in `.zshrc`. consolidate zshrc content tests into a single priorities test
This commit is contained in:
parent
1878091234
commit
7832b5aa95
4 changed files with 177 additions and 117 deletions
|
@ -2129,6 +2129,17 @@ in {
|
|||
Cohere, Groq).
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
time = "2025-03-11T02:34:43+00:00";
|
||||
condition = config.programs.zsh.enable;
|
||||
message = ''
|
||||
A new module is available: 'programs.zsh.initContent'.
|
||||
|
||||
initContent option allows you to set the content of the zshrc file,
|
||||
you can use `lib.mkOrder` to specify the order of the content you want to insert.
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -471,6 +471,15 @@ in
|
|||
description = "Environment variables that will be set for zsh session.";
|
||||
};
|
||||
|
||||
initContent = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
example = lib.mkOrder 1000 ''
|
||||
echo "Hello, initContent!"
|
||||
'';
|
||||
description = "Content to be added to {file}`.zshrc`. To specify the order, use `lib.mkOrder`.";
|
||||
};
|
||||
|
||||
initExtraBeforeCompInit = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
|
@ -616,158 +625,161 @@ in
|
|||
++ optional cfg.enableCompletion pkgs.nix-zsh-completions
|
||||
++ optional cfg.oh-my-zsh.enable cfg.oh-my-zsh.package;
|
||||
|
||||
home.file."${relToDotDir ".zshrc"}".text = concatStringsSep "\n" ([
|
||||
programs.zsh.initContent = mkMerge [
|
||||
# zprof must be loaded before everything else, since it
|
||||
# benchmarks the shell initialization.
|
||||
(optionalString cfg.zprof.enable ''
|
||||
(mkOrder 400 (optionalString cfg.zprof.enable ''
|
||||
zmodload zsh/zprof
|
||||
'')
|
||||
''))
|
||||
|
||||
cfg.initExtraFirst
|
||||
"typeset -U path cdpath fpath manpath"
|
||||
(mkOrder 550 cfg.initExtraFirst)
|
||||
(mkOrder 600 "typeset -U path cdpath fpath manpath")
|
||||
|
||||
(optionalString (cfg.cdpath != []) ''
|
||||
(mkOrder 650 (optionalString (cfg.cdpath != [ ]) ''
|
||||
cdpath+=(${concatStringsSep " " cfg.cdpath})
|
||||
''))
|
||||
(mkOrder 700 ''
|
||||
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
|
||||
|
||||
HELPDIR="${cfg.package}/share/zsh/$ZSH_VERSION/help"
|
||||
'')
|
||||
|
||||
''
|
||||
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
|
||||
|
||||
HELPDIR="${cfg.package}/share/zsh/$ZSH_VERSION/help"
|
||||
''
|
||||
|
||||
(optionalString (cfg.defaultKeymap != null) ''
|
||||
(mkOrder 750 (optionalString (cfg.defaultKeymap != null) ''
|
||||
# Use ${cfg.defaultKeymap} keymap as the default.
|
||||
${getAttr cfg.defaultKeymap bindkeyCommands}
|
||||
'')
|
||||
localVarsStr
|
||||
''))
|
||||
|
||||
cfg.initExtraBeforeCompInit
|
||||
(mkOrder 800 localVarsStr)
|
||||
(mkOrder 850 cfg.initExtraBeforeCompInit)
|
||||
|
||||
(concatStrings (map (plugin: ''
|
||||
(mkOrder 900 (concatStrings (map (plugin: ''
|
||||
path+="$HOME/${pluginsDir}/${plugin.name}"
|
||||
fpath+="$HOME/${pluginsDir}/${plugin.name}"
|
||||
'') cfg.plugins))
|
||||
'') cfg.plugins)))
|
||||
|
||||
''
|
||||
# Oh-My-Zsh/Prezto calls compinit during initialization,
|
||||
# calling it twice causes slight start up slowdown
|
||||
# as all $fpath entries will be traversed again.
|
||||
${optionalString (cfg.enableCompletion && !cfg.oh-my-zsh.enable && !cfg.prezto.enable)
|
||||
cfg.completionInit
|
||||
}''
|
||||
(mkOrder 950 ''
|
||||
# Oh-My-Zsh/Prezto calls compinit during initialization,
|
||||
# calling it twice causes slight start up slowdown
|
||||
# as all $fpath entries will be traversed again.
|
||||
${optionalString
|
||||
(cfg.enableCompletion && !cfg.oh-my-zsh.enable && !cfg.prezto.enable)
|
||||
cfg.completionInit}'')
|
||||
|
||||
(optionalString cfg.autosuggestion.enable ''
|
||||
(mkOrder 1000 (optionalString cfg.autosuggestion.enable ''
|
||||
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
|
||||
${optionalString (cfg.autosuggestion.strategy != []) ''
|
||||
ZSH_AUTOSUGGEST_STRATEGY=(${concatStringsSep " " cfg.autosuggestion.strategy})
|
||||
''
|
||||
}
|
||||
'')
|
||||
(optionalString (cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) ''
|
||||
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}"
|
||||
${optionalString (cfg.autosuggestion.strategy != [ ]) ''
|
||||
ZSH_AUTOSUGGEST_STRATEGY=(${
|
||||
concatStringsSep " " cfg.autosuggestion.strategy
|
||||
})
|
||||
''}
|
||||
''))
|
||||
(mkOrder 1050 (optionalString
|
||||
(cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) ''
|
||||
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}"
|
||||
''))
|
||||
|
||||
(mkOrder 1100 (optionalString cfg.oh-my-zsh.enable ''
|
||||
# oh-my-zsh extra settings for plugins
|
||||
${cfg.oh-my-zsh.extraConfig}
|
||||
# oh-my-zsh configuration generated by NixOS
|
||||
${optionalString (cfg.oh-my-zsh.plugins != [ ])
|
||||
"plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})"}
|
||||
${optionalString (cfg.oh-my-zsh.custom != "")
|
||||
''ZSH_CUSTOM="${cfg.oh-my-zsh.custom}"''}
|
||||
${optionalString (cfg.oh-my-zsh.theme != "")
|
||||
''ZSH_THEME="${cfg.oh-my-zsh.theme}"''}
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
''))
|
||||
(mkOrder 1150 ''
|
||||
${optionalString cfg.prezto.enable (builtins.readFile
|
||||
"${cfg.prezto.package}/share/zsh-prezto/runcoms/zshrc")}
|
||||
|
||||
${concatStrings (map (plugin: ''
|
||||
if [[ -f "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" ]]; then
|
||||
source "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}"
|
||||
fi
|
||||
'') cfg.plugins)}
|
||||
|
||||
# History options should be set in .zshrc and after oh-my-zsh sourcing.
|
||||
# See https://github.com/nix-community/home-manager/issues/177.
|
||||
HISTSIZE="${toString cfg.history.size}"
|
||||
SAVEHIST="${toString cfg.history.save}"
|
||||
${optionalString (cfg.history.ignorePatterns != [ ])
|
||||
"HISTORY_IGNORE=${
|
||||
lib.escapeShellArg
|
||||
"(${lib.concatStringsSep "|" cfg.history.ignorePatterns})"
|
||||
}"}
|
||||
${if versionAtLeast config.home.stateVersion "20.03" then
|
||||
''HISTFILE="${cfg.history.path}"''
|
||||
else
|
||||
''HISTFILE="$HOME/${cfg.history.path}"''}
|
||||
mkdir -p "$(dirname "$HISTFILE")"
|
||||
|
||||
setopt HIST_FCNTL_LOCK
|
||||
${if cfg.history.append then "setopt" else "unsetopt"} APPEND_HISTORY
|
||||
${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS
|
||||
${if cfg.history.ignoreAllDups then "setopt" else "unsetopt"} HIST_IGNORE_ALL_DUPS
|
||||
${if cfg.history.saveNoDups then "setopt" else "unsetopt"} HIST_SAVE_NO_DUPS
|
||||
${if cfg.history.findNoDups then "setopt" else "unsetopt"} HIST_FIND_NO_DUPS
|
||||
${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE
|
||||
${if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt"} HIST_EXPIRE_DUPS_FIRST
|
||||
${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY
|
||||
${if cfg.history.extended then "setopt" else "unsetopt"} EXTENDED_HISTORY
|
||||
${if cfg.autocd != null then "${if cfg.autocd then "setopt" else "unsetopt"} autocd" else ""}
|
||||
'')
|
||||
|
||||
(optionalString cfg.oh-my-zsh.enable ''
|
||||
# oh-my-zsh extra settings for plugins
|
||||
${cfg.oh-my-zsh.extraConfig}
|
||||
# oh-my-zsh configuration generated by NixOS
|
||||
${optionalString (cfg.oh-my-zsh.plugins != [])
|
||||
"plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})"
|
||||
}
|
||||
${optionalString (cfg.oh-my-zsh.custom != "")
|
||||
"ZSH_CUSTOM=\"${cfg.oh-my-zsh.custom}\""
|
||||
}
|
||||
${optionalString (cfg.oh-my-zsh.theme != "")
|
||||
"ZSH_THEME=\"${cfg.oh-my-zsh.theme}\""
|
||||
}
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
'')
|
||||
|
||||
''
|
||||
${optionalString cfg.prezto.enable
|
||||
(builtins.readFile "${cfg.prezto.package}/share/zsh-prezto/runcoms/zshrc")}
|
||||
|
||||
${concatStrings (map (plugin: ''
|
||||
if [[ -f "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" ]]; then
|
||||
source "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}"
|
||||
fi
|
||||
'') cfg.plugins)}
|
||||
|
||||
# History options should be set in .zshrc and after oh-my-zsh sourcing.
|
||||
# See https://github.com/nix-community/home-manager/issues/177.
|
||||
HISTSIZE="${toString cfg.history.size}"
|
||||
SAVEHIST="${toString cfg.history.save}"
|
||||
${optionalString (cfg.history.ignorePatterns != []) "HISTORY_IGNORE=${lib.escapeShellArg "(${lib.concatStringsSep "|" cfg.history.ignorePatterns})"}"}
|
||||
${if versionAtLeast config.home.stateVersion "20.03"
|
||||
then ''HISTFILE="${cfg.history.path}"''
|
||||
else ''HISTFILE="$HOME/${cfg.history.path}"''}
|
||||
mkdir -p "$(dirname "$HISTFILE")"
|
||||
|
||||
setopt HIST_FCNTL_LOCK
|
||||
${if cfg.history.append then "setopt" else "unsetopt"} APPEND_HISTORY
|
||||
${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS
|
||||
${if cfg.history.ignoreAllDups then "setopt" else "unsetopt"} HIST_IGNORE_ALL_DUPS
|
||||
${if cfg.history.saveNoDups then "setopt" else "unsetopt"} HIST_SAVE_NO_DUPS
|
||||
${if cfg.history.findNoDups then "setopt" else "unsetopt"} HIST_FIND_NO_DUPS
|
||||
${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE
|
||||
${if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt"} HIST_EXPIRE_DUPS_FIRST
|
||||
${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY
|
||||
${if cfg.history.extended then "setopt" else "unsetopt"} EXTENDED_HISTORY
|
||||
${if cfg.autocd != null then "${if cfg.autocd then "setopt" else "unsetopt"} autocd" else ""}
|
||||
|
||||
${cfg.initExtra}
|
||||
(mkOrder 1200 cfg.initExtra)
|
||||
|
||||
# Aliases
|
||||
${aliasesStr}
|
||||
''
|
||||
]
|
||||
++ (mapAttrsToList (k: v: "alias -g -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases)
|
||||
++ [ (''
|
||||
# Named Directory Hashes
|
||||
${dirHashesStr}
|
||||
(mkOrder 1250 aliasesStr)
|
||||
(mkOrder 1250 (concatStringsSep "\n" (mapAttrsToList
|
||||
(k: v: "alias -g -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}")
|
||||
cfg.shellGlobalAliases)))
|
||||
(mkOrder 1300 ''
|
||||
# Named Directory Hashes
|
||||
${dirHashesStr}
|
||||
'')
|
||||
|
||||
(optionalString cfg.syntaxHighlighting.enable
|
||||
(mkOrder 1350 (optionalString cfg.syntaxHighlighting.enable
|
||||
# Load zsh-syntax-highlighting after all custom widgets have been created
|
||||
# https://github.com/zsh-users/zsh-syntax-highlighting#faq
|
||||
''
|
||||
source ${cfg.syntaxHighlighting.package}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(${lib.concatStringsSep " " (map lib.escapeShellArg cfg.syntaxHighlighting.highlighters)})
|
||||
${lib.concatStringsSep "\n" (
|
||||
''
|
||||
source ${cfg.syntaxHighlighting.package}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(${lib.concatStringsSep " " (map lib.escapeShellArg cfg.syntaxHighlighting.highlighters)})
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList
|
||||
(name: value: "ZSH_HIGHLIGHT_STYLES[${lib.escapeShellArg name}]=${lib.escapeShellArg value}")
|
||||
(name: value: "ZSH_HIGHLIGHT_STYLES[${lib.escapeShellArg name}]=${lib.escapeShellArg value}")
|
||||
cfg.syntaxHighlighting.styles
|
||||
)}
|
||||
${lib.concatStringsSep "\n" (
|
||||
)}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList
|
||||
(name: value: "ZSH_HIGHLIGHT_PATTERNS+=(${lib.escapeShellArg name} ${lib.escapeShellArg value})")
|
||||
cfg.syntaxHighlighting.patterns
|
||||
)}
|
||||
'')
|
||||
)}
|
||||
''))
|
||||
|
||||
(optionalString (cfg.historySubstringSearch.enable or false)
|
||||
(mkOrder 1400 (optionalString
|
||||
(cfg.historySubstringSearch.enable or false)
|
||||
# Load zsh-history-substring-search after zsh-syntax-highlighting
|
||||
# https://github.com/zsh-users/zsh-history-substring-search#usage
|
||||
''
|
||||
source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh
|
||||
${lib.concatMapStringsSep "\n"
|
||||
(upKey: "bindkey \"${upKey}\" history-substring-search-up")
|
||||
(lib.toList cfg.historySubstringSearch.searchUpKey)
|
||||
}
|
||||
${lib.concatMapStringsSep "\n"
|
||||
(downKey: "bindkey \"${downKey}\" history-substring-search-down")
|
||||
(lib.toList cfg.historySubstringSearch.searchDownKey)
|
||||
}
|
||||
'')
|
||||
''
|
||||
source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh
|
||||
${lib.concatMapStringsSep "\n"
|
||||
(upKey: ''bindkey "${upKey}" history-substring-search-up'')
|
||||
(lib.toList cfg.historySubstringSearch.searchUpKey)}
|
||||
${lib.concatMapStringsSep "\n"
|
||||
(downKey: ''bindkey "${downKey}" history-substring-search-down'')
|
||||
(lib.toList cfg.historySubstringSearch.searchDownKey)}
|
||||
''))
|
||||
|
||||
(optionalString cfg.zprof.enable
|
||||
''
|
||||
(mkOrder 1450 (optionalString cfg.zprof.enable ''
|
||||
zprof
|
||||
'')
|
||||
]);
|
||||
''))
|
||||
];
|
||||
|
||||
home.file."${relToDotDir ".zshrc"}".text = cfg.initContent;
|
||||
}
|
||||
|
||||
(mkIf cfg.oh-my-zsh.enable {
|
||||
|
|
|
@ -9,4 +9,5 @@
|
|||
zsh-prezto = ./prezto.nix;
|
||||
zsh-syntax-highlighting = ./syntax-highlighting.nix;
|
||||
zsh-abbr = ./zsh-abbr.nix;
|
||||
zshrc-contents-priorities = ./zshrc-content-priorities.nix;
|
||||
}
|
||||
|
|
36
tests/modules/programs/zsh/zshrc-content-priorities.nix
Normal file
36
tests/modules/programs/zsh/zshrc-content-priorities.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ lib, ... }: {
|
||||
programs.zsh = {
|
||||
enable = true;
|
||||
|
||||
initContent = lib.mkMerge [
|
||||
(lib.mkBefore ''
|
||||
# High priority (mkBefore)
|
||||
echo "High priority content"
|
||||
'')
|
||||
|
||||
(lib.mkAfter ''
|
||||
# Low priority (mkAfter)
|
||||
echo "Low priority content"
|
||||
'')
|
||||
|
||||
''
|
||||
# Default priority
|
||||
echo "Default priority content"
|
||||
''
|
||||
];
|
||||
|
||||
zprof.enable = true;
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.zshrc
|
||||
|
||||
assertFileContains home-files/.zshrc "zmodload zsh/zprof"
|
||||
assertFileContains home-files/.zshrc "High priority content"
|
||||
assertFileContains home-files/.zshrc "Default priority content"
|
||||
assertFileContains home-files/.zshrc "Low priority content"
|
||||
|
||||
assertFileRegex home-files/.zshrc '^zmodload zsh/zprof'
|
||||
assertFileRegex home-files/.zshrc 'echo "Low priority content"$'
|
||||
'';
|
||||
}
|
Loading…
Add table
Reference in a new issue