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 // { which = "type -P"; };
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.
94 PROMPT_COLOR="1;31m"
95 let $UID && PROMPT_COLOR="1;32m"
96 PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
97 if test "$TERM" = "xterm"; then
98 PS1="\[\033]2;\h:\u:\w\007\]$PS1"
99 fi
100 '';
101 description = ''
102 Shell script code used to initialise the bash prompt.
103 '';
104 type = types.lines;
105 };
106
107 enableCompletion = mkOption {
108 default = false;
109 description = ''
110 Enable Bash completion for all interactive bash shells.
111 '';
112 type = types.bool;
113 };
114
115 };
116
117 };
118
119 config = /* mkIf cfg.enable */ {
120
121 programs.bash = {
122
123 shellInit = ''
124 . ${config.system.build.setEnvironment}
125
126 ${cfge.shellInit}
127 '';
128
129 loginShellInit = cfge.loginShellInit;
130
131 interactiveShellInit = ''
132 # Check the window size after every command.
133 shopt -s checkwinsize
134
135 # Disable hashing (i.e. caching) of command lookups.
136 set +h
137
138 ${cfg.promptInit}
139 ${bashCompletion}
140 ${bashAliases}
141
142 ${cfge.interactiveShellInit}
143 '';
144
145 };
146
147 environment.etc."profile".text =
148 ''
149 # /etc/profile: DO NOT EDIT -- this file has been generated automatically.
150 # This file is read for login shells.
151
152 # Only execute this file once per shell.
153 if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
154 __ETC_PROFILE_SOURCED=1
155
156 # Prevent this file from being sourced by interactive non-login child shells.
157 export __ETC_PROFILE_DONE=1
158
159 ${cfg.shellInit}
160 ${cfg.loginShellInit}
161
162 # Read system-wide modifications.
163 if test -f /etc/profile.local; then
164 . /etc/profile.local
165 fi
166
167 if [ -n "''${BASH_VERSION:-}" ]; then
168 . /etc/bashrc
169 fi
170 '';
171
172 environment.etc."bashrc".text =
173 ''
174 # /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
175
176 # Only execute this file once per shell.
177 if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
178 __ETC_BASHRC_SOURCED=1
179
180 # If the profile was not loaded in a parent process, source
181 # it. But otherwise don't do it because we don't want to
182 # clobber overridden values of $PATH, etc.
183 if [ -z "$__ETC_PROFILE_DONE" ]; then
184 . /etc/profile
185 fi
186
187 # We are not always an interactive shell.
188 if [ -n "$PS1" ]; then
189 ${cfg.interactiveShellInit}
190 fi
191
192 # Read system-wide modifications.
193 if test -f /etc/bashrc.local; then
194 . /etc/bashrc.local
195 fi
196 '';
197
198 # Configuration for readline in bash.
199 environment.etc."inputrc".source = ./inputrc;
200
201 users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash";
202
203 environment.pathsToLink = optionals cfg.enableCompletion [
204 "/etc/bash_completion.d"
205 "/share/bash-completion"
206 ];
207
208 environment.shells =
209 [ "/run/current-system/sw/bin/bash"
210 "/var/run/current-system/sw/bin/bash"
211 "/run/current-system/sw/bin/sh"
212 "/var/run/current-system/sw/bin/sh"
213 "${pkgs.bashInteractive}/bin/bash"
214 "${pkgs.bashInteractive}/bin/sh"
215 ];
216
217 };
218
219}