1# This module defines global configuration for the Bash shell, in
2# particular /etc/bashrc and /etc/profile.
3
4{ config, lib, pkgs, ... }:
5
6with lib;
7
8let
9
10 cfge = config.environment;
11
12 cfg = config.programs.bash;
13
14 bashCompletion = optionalString cfg.enableCompletion ''
15 # Check whether we're running a version of Bash that has support for
16 # programmable completion. If we do, enable all modules installed in
17 # the system (and user profile).
18 if shopt -q progcomp &>/dev/null; then
19 . "${pkgs.bashCompletion}/etc/profile.d/bash_completion.sh"
20 nullglobStatus=$(shopt -p nullglob)
21 shopt -s nullglob
22 for p in $NIX_PROFILES; do
23 for m in "$p/etc/bash_completion.d/"* "$p/share/bash-completion/completions/"*; do
24 . $m
25 done
26 done
27 eval "$nullglobStatus"
28 unset nullglobStatus p m
29 fi
30 '';
31
32 bashAliases = concatStringsSep "\n" (
33 mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases
34 );
35
36in
37
38{
39 options = {
40
41 programs.bash = {
42
43 /*
44 enable = mkOption {
45 default = true;
46 description = ''
47 Whenever to configure Bash as an interactive shell.
48 Note that this tries to make Bash the default
49 <option>users.defaultUserShell</option>,
50 which in turn means that you might need to explicitly
51 set this variable if you have another shell configured
52 with NixOS.
53 '';
54 type = types.bool;
55 };
56 */
57
58 shellAliases = mkOption {
59 default = config.environment.shellAliases;
60 description = ''
61 Set of aliases for bash shell. See <option>environment.shellAliases</option>
62 for an option format description.
63 '';
64 type = types.attrs; # types.attrsOf types.stringOrPath;
65 };
66
67 shellInit = mkOption {
68 default = "";
69 description = ''
70 Shell script code called during bash shell initialisation.
71 '';
72 type = types.lines;
73 };
74
75 loginShellInit = mkOption {
76 default = "";
77 description = ''
78 Shell script code called during login bash shell initialisation.
79 '';
80 type = types.lines;
81 };
82
83 interactiveShellInit = mkOption {
84 default = "";
85 description = ''
86 Shell script code called during interactive bash shell initialisation.
87 '';
88 type = types.lines;
89 };
90
91 promptInit = mkOption {
92 default = ''
93 # Provide a nice prompt if the terminal supports it.
94 if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then
95 PROMPT_COLOR="1;31m"
96 let $UID && PROMPT_COLOR="1;32m"
97 PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
98 if test "$TERM" = "xterm"; then
99 PS1="\[\033]2;\h:\u:\w\007\]$PS1"
100 fi
101 fi
102 '';
103 description = ''
104 Shell script code used to initialise the bash prompt.
105 '';
106 type = types.lines;
107 };
108
109 enableCompletion = mkOption {
110 default = false;
111 description = ''
112 Enable Bash completion for all interactive bash shells.
113 '';
114 type = types.bool;
115 };
116
117 };
118
119 };
120
121 config = /* mkIf cfg.enable */ {
122
123 programs.bash = {
124
125 shellInit = ''
126 . ${config.system.build.setEnvironment}
127
128 ${cfge.shellInit}
129 '';
130
131 loginShellInit = cfge.loginShellInit;
132
133 interactiveShellInit = ''
134 # Check the window size after every command.
135 shopt -s checkwinsize
136
137 # Disable hashing (i.e. caching) of command lookups.
138 set +h
139
140 ${cfg.promptInit}
141 ${bashCompletion}
142 ${bashAliases}
143
144 ${cfge.interactiveShellInit}
145 '';
146
147 };
148
149 environment.etc."profile".text =
150 ''
151 # /etc/profile: DO NOT EDIT -- this file has been generated automatically.
152 # This file is read for login shells.
153
154 # Only execute this file once per shell.
155 if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
156 __ETC_PROFILE_SOURCED=1
157
158 # Prevent this file from being sourced by interactive non-login child shells.
159 export __ETC_PROFILE_DONE=1
160
161 ${cfg.shellInit}
162 ${cfg.loginShellInit}
163
164 # Read system-wide modifications.
165 if test -f /etc/profile.local; then
166 . /etc/profile.local
167 fi
168
169 if [ -n "''${BASH_VERSION:-}" ]; then
170 . /etc/bashrc
171 fi
172 '';
173
174 environment.etc."bashrc".text =
175 ''
176 # /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
177
178 # Only execute this file once per shell.
179 if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
180 __ETC_BASHRC_SOURCED=1
181
182 # If the profile was not loaded in a parent process, source
183 # it. But otherwise don't do it because we don't want to
184 # clobber overridden values of $PATH, etc.
185 if [ -z "$__ETC_PROFILE_DONE" ]; then
186 . /etc/profile
187 fi
188
189 # We are not always an interactive shell.
190 if [ -n "$PS1" ]; then
191 ${cfg.interactiveShellInit}
192 fi
193
194 # Read system-wide modifications.
195 if test -f /etc/bashrc.local; then
196 . /etc/bashrc.local
197 fi
198 '';
199
200 # Configuration for readline in bash.
201 environment.etc."inputrc".source = ./inputrc;
202
203 users.defaultUserShell = mkDefault pkgs.bashInteractive;
204
205 environment.pathsToLink = optionals cfg.enableCompletion [
206 "/etc/bash_completion.d"
207 "/share/bash-completion"
208 ];
209
210 environment.shells =
211 [ "/run/current-system/sw/bin/bash"
212 "/var/run/current-system/sw/bin/bash"
213 "/run/current-system/sw/bin/sh"
214 "/var/run/current-system/sw/bin/sh"
215 "${pkgs.bashInteractive}/bin/bash"
216 "${pkgs.bashInteractive}/bin/sh"
217 ];
218
219 };
220
221}