1# This module defines global configuration for the zshell.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8
9 cfge = config.environment;
10
11 cfg = config.programs.zsh;
12
13 zshAliases = concatStringsSep "\n" (
14 mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
15 (filterAttrs (k: v: v != null) cfg.shellAliases)
16 );
17
18 zshStartupNotes = ''
19 # Note that generated /etc/zprofile and /etc/zshrc files do a lot of
20 # non-standard setup to make zsh usable with no configuration by default.
21 #
22 # Which means that unless you explicitly meticulously override everything
23 # generated, interactions between your ~/.zshrc and these files are likely
24 # to be rather surprising.
25 #
26 # Note however, that you can disable loading of the generated /etc/zprofile
27 # and /etc/zshrc (you can't disable loading of /etc/zshenv, but it is
28 # designed to not set anything surprising) by setting `no_global_rcs` option
29 # in ~/.zshenv:
30 #
31 # echo setopt no_global_rcs >> ~/.zshenv
32 #
33 # See "STARTUP/SHUTDOWN FILES" section of zsh(1) for more info.
34 '';
35
36in
37
38{
39
40 options = {
41
42 programs.zsh = {
43
44 enable = mkOption {
45 default = false;
46 description = ''
47 Whether to configure zsh as an interactive shell. To enable zsh for
48 a particular user, use the <option>users.users.<name?>.shell</option>
49 option for that user. To enable zsh system-wide use the
50 <option>users.defaultUserShell</option> option.
51 '';
52 type = types.bool;
53 };
54
55 shellAliases = mkOption {
56 default = {};
57 description = ''
58 Set of aliases for zsh shell, which overrides <option>environment.shellAliases</option>.
59 See <option>environment.shellAliases</option> for an option format description.
60 '';
61 type = with types; attrsOf (nullOr (either str path));
62 };
63
64 shellInit = mkOption {
65 default = "";
66 description = ''
67 Shell script code called during zsh shell initialisation.
68 '';
69 type = types.lines;
70 };
71
72 loginShellInit = mkOption {
73 default = "";
74 description = ''
75 Shell script code called during zsh login shell initialisation.
76 '';
77 type = types.lines;
78 };
79
80 interactiveShellInit = mkOption {
81 default = "";
82 description = ''
83 Shell script code called during interactive zsh shell initialisation.
84 '';
85 type = types.lines;
86 };
87
88 promptInit = mkOption {
89 default = ''
90 # Note that to manually override this in ~/.zshrc you should run `prompt off`
91 # before setting your PS1 and etc. Otherwise this will likely to interact with
92 # your ~/.zshrc configuration in unexpected ways as the default prompt sets
93 # a lot of different prompt variables.
94 autoload -U promptinit && promptinit && prompt walters && setopt prompt_sp
95 '';
96 description = ''
97 Shell script code used to initialise the zsh prompt.
98 '';
99 type = types.lines;
100 };
101
102 histSize = mkOption {
103 default = 2000;
104 description = ''
105 Change history size.
106 '';
107 type = types.int;
108 };
109
110 histFile = mkOption {
111 default = "$HOME/.zsh_history";
112 description = ''
113 Change history file.
114 '';
115 type = types.str;
116 };
117
118 setOptions = mkOption {
119 type = types.listOf types.str;
120 default = [
121 "HIST_IGNORE_DUPS" "SHARE_HISTORY" "HIST_FCNTL_LOCK"
122 ];
123 example = [ "EXTENDED_HISTORY" "RM_STAR_WAIT" ];
124 description = ''
125 Configure zsh options. See
126 <citerefentry><refentrytitle>zshoptions</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
127 '';
128 };
129
130 enableCompletion = mkOption {
131 default = true;
132 description = ''
133 Enable zsh completion for all interactive zsh shells.
134 '';
135 type = types.bool;
136 };
137
138 enableBashCompletion = mkOption {
139 default = false;
140 description = ''
141 Enable compatibility with bash's programmable completion system.
142 '';
143 type = types.bool;
144 };
145
146 enableGlobalCompInit = mkOption {
147 default = cfg.enableCompletion;
148 description = ''
149 Enable execution of compinit call for all interactive zsh shells.
150
151 This option can be disabled if the user wants to extend its
152 <literal>fpath</literal> and a custom <literal>compinit</literal>
153 call in the local config is required.
154 '';
155 type = types.bool;
156 };
157
158 };
159
160 };
161
162 config = mkIf cfg.enable {
163
164 programs.zsh.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
165
166 environment.etc.zshenv.text =
167 ''
168 # /etc/zshenv: DO NOT EDIT -- this file has been generated automatically.
169 # This file is read for all shells.
170
171 # Only execute this file once per shell.
172 if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
173 __ETC_ZSHENV_SOURCED=1
174
175 if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
176 . ${config.system.build.setEnvironment}
177 fi
178
179 HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
180
181 # Tell zsh how to find installed completions.
182 for p in ''${(z)NIX_PROFILES}; do
183 fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
184 done
185
186 # Setup custom shell init stuff.
187 ${cfge.shellInit}
188
189 ${cfg.shellInit}
190
191 # Read system-wide modifications.
192 if test -f /etc/zshenv.local; then
193 . /etc/zshenv.local
194 fi
195 '';
196
197 environment.etc.zprofile.text =
198 ''
199 # /etc/zprofile: DO NOT EDIT -- this file has been generated automatically.
200 # This file is read for login shells.
201 #
202 ${zshStartupNotes}
203
204 # Only execute this file once per shell.
205 if [ -n "$__ETC_ZPROFILE_SOURCED" ]; then return; fi
206 __ETC_ZPROFILE_SOURCED=1
207
208 # Setup custom login shell init stuff.
209 ${cfge.loginShellInit}
210
211 ${cfg.loginShellInit}
212
213 # Read system-wide modifications.
214 if test -f /etc/zprofile.local; then
215 . /etc/zprofile.local
216 fi
217 '';
218
219 environment.etc.zshrc.text =
220 ''
221 # /etc/zshrc: DO NOT EDIT -- this file has been generated automatically.
222 # This file is read for interactive shells.
223 #
224 ${zshStartupNotes}
225
226 # Only execute this file once per shell.
227 if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
228 __ETC_ZSHRC_SOURCED=1
229
230 ${optionalString (cfg.setOptions != []) ''
231 # Set zsh options.
232 setopt ${concatStringsSep " " cfg.setOptions}
233 ''}
234
235 # Setup command line history.
236 # Don't export these, otherwise other shells (bash) will try to use same HISTFILE.
237 SAVEHIST=${toString cfg.histSize}
238 HISTSIZE=${toString cfg.histSize}
239 HISTFILE=${cfg.histFile}
240
241 # Configure sane keyboard defaults.
242 . /etc/zinputrc
243
244 ${optionalString cfg.enableGlobalCompInit ''
245 # Enable autocompletion.
246 autoload -U compinit && compinit
247 ''}
248
249 ${optionalString cfg.enableBashCompletion ''
250 # Enable compatibility with bash's completion system.
251 autoload -U bashcompinit && bashcompinit
252 ''}
253
254 # Setup custom interactive shell init stuff.
255 ${cfge.interactiveShellInit}
256
257 ${cfg.interactiveShellInit}
258
259 # Setup aliases.
260 ${zshAliases}
261
262 # Setup prompt.
263 ${cfg.promptInit}
264
265 # Disable some features to support TRAMP.
266 if [ "$TERM" = dumb ]; then
267 unsetopt zle prompt_cr prompt_subst
268 unset RPS1 RPROMPT
269 PS1='$ '
270 PROMPT='$ '
271 fi
272
273 # Read system-wide modifications.
274 if test -f /etc/zshrc.local; then
275 . /etc/zshrc.local
276 fi
277 '';
278
279 environment.etc.zinputrc.source = ./zinputrc;
280
281 environment.systemPackages = [ pkgs.zsh ]
282 ++ optional cfg.enableCompletion pkgs.nix-zsh-completions;
283
284 environment.pathsToLink = optional cfg.enableCompletion "/share/zsh";
285
286 #users.defaultUserShell = mkDefault "/run/current-system/sw/bin/zsh";
287
288 environment.shells =
289 [ "/run/current-system/sw/bin/zsh"
290 "${pkgs.zsh}/bin/zsh"
291 ];
292
293 };
294
295}