summaryrefslogtreecommitdiffstats
path: root/nixos/modules/programs/bash
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
commit5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010 (patch)
treea6c0f605be6de3f372ae69905b331f9f75452da7 /nixos/modules/programs/bash
parent6070bc016bd2fd945b04347e25cfd3738622d2ac (diff)
Move all of NixOS to nixos/ in preparation of the repository merge
Diffstat (limited to 'nixos/modules/programs/bash')
-rw-r--r--nixos/modules/programs/bash/bash.nix217
-rw-r--r--nixos/modules/programs/bash/command-not-found.nix51
-rw-r--r--nixos/modules/programs/bash/command-not-found.pl48
-rw-r--r--nixos/modules/programs/bash/inputrc36
4 files changed, 352 insertions, 0 deletions
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
new file mode 100644
index 000000000000..8cfe3f990adc
--- /dev/null
+++ b/nixos/modules/programs/bash/bash.nix
@@ -0,0 +1,217 @@
+# This module defines global configuration for the Bash shell, in
+# particular /etc/bashrc and /etc/profile.
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+ cfge = config.environment;
+
+ cfg = config.programs.bash;
+
+ bashCompletion = optionalString cfg.enableCompletion ''
+ # Check whether we're running a version of Bash that has support for
+ # programmable completion. If we do, enable all modules installed in
+ # the system (and user profile).
+ if shopt -q progcomp &>/dev/null; then
+ . "${pkgs.bashCompletion}/etc/profile.d/bash_completion.sh"
+ nullglobStatus=$(shopt -p nullglob)
+ shopt -s nullglob
+ for p in $NIX_PROFILES; do
+ for m in "$p/etc/bash_completion.d/"* "$p/share/bash-completion/completions/"*; do
+ . $m
+ done
+ done
+ eval "$nullglobStatus"
+ unset nullglobStatus p m
+ fi
+ '';
+
+ bashAliases = concatStringsSep "\n" (
+ mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases
+ );
+
+in
+
+{
+ options = {
+
+ programs.bash = {
+
+ enable = mkOption {
+ default = true;
+ description = ''
+ Whenever to configure Bash as an interactive shell.
+ Note that this tries to make Bash the default
+ <option>users.defaultUserShell</option>,
+ which in turn means that you might need to explicitly
+ set this variable if you have another shell configured
+ with NixOS.
+ '';
+ type = types.bool;
+ };
+
+ shellAliases = mkOption {
+ default = config.environment.shellAliases // { which = "type -P"; };
+ description = ''
+ Set of aliases for bash shell. See <option>environment.shellAliases</option>
+ for an option format description.
+ '';
+ type = types.attrs; # types.attrsOf types.stringOrPath;
+ };
+
+ shellInit = mkOption {
+ default = "";
+ description = ''
+ Shell script code called during bash shell initialisation.
+ '';
+ type = types.lines;
+ };
+
+ loginShellInit = mkOption {
+ default = "";
+ description = ''
+ Shell script code called during login bash shell initialisation.
+ '';
+ type = types.lines;
+ };
+
+ interactiveShellInit = mkOption {
+ default = "";
+ description = ''
+ Shell script code called during interactive bash shell initialisation.
+ '';
+ type = types.lines;
+ };
+
+ promptInit = mkOption {
+ default = ''
+ # Provide a nice prompt.
+ PROMPT_COLOR="1;31m"
+ let $UID && PROMPT_COLOR="1;32m"
+ PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
+ if test "$TERM" = "xterm"; then
+ PS1="\[\033]2;\h:\u:\w\007\]$PS1"
+ fi
+ '';
+ description = ''
+ Shell script code used to initialise the bash prompt.
+ '';
+ type = types.lines;
+ };
+
+ enableCompletion = mkOption {
+ default = false;
+ description = ''
+ Enable Bash completion for all interactive bash shells.
+ '';
+ type = types.bool;
+ };
+
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ programs.bash = {
+
+ shellInit = ''
+ . ${config.system.build.setEnvironment}
+
+ ${cfge.shellInit}
+ '';
+
+ loginShellInit = cfge.loginShellInit;
+
+ interactiveShellInit = ''
+ ${cfge.interactiveShellInit}
+
+ # Check the window size after every command.
+ shopt -s checkwinsize
+
+ # Disable hashing (i.e. caching) of command lookups.
+ set +h
+
+ ${cfg.promptInit}
+ ${bashCompletion}
+ ${bashAliases}
+ '';
+
+ };
+
+ environment.etc."profile".text =
+ ''
+ # /etc/profile: DO NOT EDIT -- this file has been generated automatically.
+ # This file is read for login shells.
+
+ # Only execute this file once per shell.
+ if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
+ __ETC_PROFILE_SOURCED=1
+
+ # Prevent this file from being sourced by interactive non-login child shells.
+ export __ETC_PROFILE_DONE=1
+
+ ${cfg.shellInit}
+ ${cfg.loginShellInit}
+
+ # Read system-wide modifications.
+ if test -f /etc/profile.local; then
+ . /etc/profile.local
+ fi
+
+ if [ -n "''${BASH_VERSION:-}" ]; then
+ . /etc/bashrc
+ fi
+ '';
+
+ environment.etc."bashrc".text =
+ ''
+ # /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
+
+ # Only execute this file once per shell.
+ if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
+ __ETC_BASHRC_SOURCED=1
+
+ # If the profile was not loaded in a parent process, source
+ # it. But otherwise don't do it because we don't want to
+ # clobber overridden values of $PATH, etc.
+ if [ -z "$__ETC_PROFILE_DONE" ]; then
+ . /etc/profile
+ fi
+
+ # We are not always an interactive shell.
+ if [ -n "$PS1" ]; then
+ ${cfg.interactiveShellInit}
+ fi
+
+ # Read system-wide modifications.
+ if test -f /etc/bashrc.local; then
+ . /etc/bashrc.local
+ fi
+ '';
+
+ # Configuration for readline in bash.
+ environment.etc."inputrc".source = ./inputrc;
+
+ users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash";
+
+ environment.pathsToLink = optionals cfg.enableCompletion [
+ "/etc/bash_completion.d"
+ "/share/bash-completion"
+ ];
+
+ environment.shells =
+ [ "/run/current-system/sw/bin/bash"
+ "/var/run/current-system/sw/bin/bash"
+ "/run/current-system/sw/bin/sh"
+ "/var/run/current-system/sw/bin/sh"
+ "${pkgs.bashInteractive}/bin/bash"
+ "${pkgs.bashInteractive}/bin/sh"
+ ];
+
+ };
+
+}
diff --git a/nixos/modules/programs/bash/command-not-found.nix b/nixos/modules/programs/bash/command-not-found.nix
new file mode 100644
index 000000000000..502320446a37
--- /dev/null
+++ b/nixos/modules/programs/bash/command-not-found.nix
@@ -0,0 +1,51 @@
+# This module provides suggestions of packages to install if the user
+# tries to run a missing command in Bash. This is implemented using a
+# SQLite database that maps program names to Nix package names (e.g.,
+# "pdflatex" is mapped to "tetex").
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+ commandNotFound = pkgs.substituteAll {
+ name = "command-not-found";
+ dir = "bin";
+ src = ./command-not-found.pl;
+ isExecutable = true;
+ inherit (pkgs) perl;
+ perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ")
+ [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite ]);
+ };
+
+in
+
+{
+
+ programs.bash.interactiveShellInit =
+ ''
+ # This function is called whenever a command is not found.
+ command_not_found_handle() {
+ local p=/run/current-system/sw/bin/command-not-found
+ if [ -x $p -a -f /nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite ]; then
+ # Run the helper program.
+ $p "$1"
+ # Retry the command if we just installed it.
+ if [ $? = 126 ]; then
+ "$@"
+ else
+ return 127
+ fi
+ else
+ echo "$1: command not found" >&2
+ return 127
+ fi
+ }
+ '';
+
+ environment.systemPackages = [ commandNotFound ];
+
+ # TODO: tab completion for uninstalled commands! :-)
+
+}
diff --git a/nixos/modules/programs/bash/command-not-found.pl b/nixos/modules/programs/bash/command-not-found.pl
new file mode 100644
index 000000000000..916649059d37
--- /dev/null
+++ b/nixos/modules/programs/bash/command-not-found.pl
@@ -0,0 +1,48 @@
+#! @perl@/bin/perl -w @perlFlags@
+
+use strict;
+use DBI;
+use DBD::SQLite;
+use Config;
+
+my $program = $ARGV[0];
+
+my $dbPath = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
+
+my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
+ or die "cannot open database `$dbPath'";
+$dbh->{RaiseError} = 0;
+$dbh->{PrintError} = 0;
+
+my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname};
+
+my $res = $dbh->selectall_arrayref(
+ "select package from Programs where system = ? and name = ?",
+ { Slice => {} }, $system, $program);
+
+if (!defined $res || scalar @$res == 0) {
+ print STDERR "$program: command not found\n";
+} elsif (scalar @$res == 1) {
+ my $package = @$res[0]->{package};
+ if ($ENV{"NIX_AUTO_INSTALL"} // "") {
+ print STDERR <<EOF;
+The program ‘$program’ is currently not installed. It is provided by
+the package ‘$package’, which I will now install for you.
+EOF
+ ;
+ exit 126 if system("nix-env", "-i", $package) == 0;
+ } else {
+ print STDERR <<EOF;
+The program ‘$program’ is currently not installed. You can install it by typing:
+ nix-env -i $package
+EOF
+ }
+} else {
+ print STDERR <<EOF;
+The program ‘$program’ is currently not installed. It is provided by
+several packages. You can install it by typing one of the following:
+EOF
+ print STDERR " nix-env -i $_->{package}\n" foreach @$res;
+}
+
+exit 127;
diff --git a/nixos/modules/programs/bash/inputrc b/nixos/modules/programs/bash/inputrc
new file mode 100644
index 000000000000..e4eabc052c5f
--- /dev/null
+++ b/nixos/modules/programs/bash/inputrc
@@ -0,0 +1,36 @@
+# inputrc borrowed from CentOS (RHEL).
+
+set bell-style none
+
+set meta-flag on
+set input-meta on
+set convert-meta off
+set output-meta on
+
+#set mark-symlinked-directories on
+
+$if mode=emacs
+
+# for linux console and RH/Debian xterm
+"\e[1~": beginning-of-line
+"\e[4~": end-of-line
+"\e[5~": beginning-of-history
+"\e[6~": end-of-history
+"\e[3~": delete-char
+"\e[2~": quoted-insert
+"\e[5C": forward-word
+"\e[5D": backward-word
+"\e[1;5C": forward-word
+"\e[1;5D": backward-word
+
+# for rxvt
+"\e[8~": end-of-line
+
+# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
+"\eOH": beginning-of-line
+"\eOF": end-of-line
+
+# for freebsd console
+"\e[H": beginning-of-line
+"\e[F": end-of-line
+$endif