summaryrefslogtreecommitdiff
path: root/modules/default.nix
blob: 81cbb5ce4a8e28eb6945928a8e82313dd1d9396c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
{ config, lib, pkgs, ... }:

with lib;
let cfg = config;
in {
  imports =
    [ ./coq.nix ./golang.nix ./latex.nix ./nix.nix ./python.nix ./ocaml.nix ./why3.nix ];

  options = {
    # Inputs
    inputsFrom = mkOption {
      type = types.listOf types.package;
      default = [ ];
      description = ''
        The list of derivations whose inputs will be made available to the environment.
      '';
      example = literalExample ''
        [ pkgs.python3 ]
      '';
    };
    buildInputs = mkOption {
      type = types.listOf types.package;
      default = [ ];
      description = ''
        The list of derivations which will be made available to the environment.
      '';
      example = literalExample ''
        [ pkgs.ocamlPackages.owl ]
      '';
    };
    nativeBuildInputs = mkOption {
      type = types.listOf types.package;
      default = [ ];
      description = ''
        The list of derivations which will be made available to the environment at run-time.
      '';
      example = literalExample ''
        [ pkgs.python3 ];
      '';
    };

    # EnvVars
    envVars = mkOption {
      type = types.attrsOf (types.submodule {
        options = {
          reset = mkOption {
            type = types.bool;
            default = false;
            description = ''
              If `true`, reset the value of the variable before changing it.
              If `false`, the new value is thus set as $VAR=$VAR:`config.envVars.VAR.value`.
            '';
          };
          value = mkOption {
            type = types.envVar;
            default = "";
            description = ''
              The new value to give to the environment variable.
            '';
          };
        };
      });
      default = { };
      description = ''
        Environment variables that will be made available to the environment.
      '';
      example = {
        PATH = {
          reset = true;
          value = "~/.local/bin";
        };
      };
    };
    aliases = mkOption {
      type = types.attrsOf types.str;
      default = { };
      description = ''
        Aliases.
        If direnv is enabled, they are installed as executables in
        .direnv/aliases. They may then take arguments. This also means that
        "recursive" aliases (e.g. ssh="export A=something ssh") will fail ; the
        executable in the definition should be called by its full path (e.g.
        $\{pkgs.openssh\}/bin/ssh). 
      '';
      example = literalExample ''
        { zz = "ls -la"; };
      '';
    };

    # Misc
    ## Whether the shell is to be loaded by direnv
    direnv.enable = mkEnableOption "direnv";

    # Hooks
    shellHook = mkOption {
      type = types.lines;
      default = "";
      description = ''
        Commands to run after initializing the environment.
      '';
      example = ''
        alias ll="ls -l"
        git status
      '';
    };
    exitHook = mkOption {
      type = types.lines;
      default = "";
      description = ''
        Commands to run when exiting the shell.
      '';
      example = ''
        git clean
      '';
    };
  };

  config.shellHook = concatStringsSep "\n" (
    # Environment variables are declared in a shell hook because simply adding the
    # top-level arguments of pkgs.mkShell ovewrites the old values of the
    # variables, which may be a problem, for example for PATH.
    (let
      dollar = "$";
      makeEnvVarCommand = name:
        { reset, value }:
        ''
          export "${name}"=${
            optionalString (!reset) (''"${dollar}${name}":'')
          }"${value}"'';
    in (attrValues (mapAttrs makeEnvVarCommand cfg.envVars)))
    ++ (if cfg.direnv.enable then
      (let
        aliasDir = ''"$PWD"/.direnv/aliases'';
        makeAliasCommand = name: value:
          let target = ''${aliasDir}/${name}'';
          in ''
            echo '#!${pkgs.bash}/bin/bash -e' > "${target}"
            echo "${value}" >> "${target}"
            chmod +x "${target}"
          '';
      in ([''
        mkdir -p "${aliasDir}"
        rm -f "${aliasDir}"/*
        PATH="${aliasDir}":"$PATH" # $PATH has to come last for the alias to take effect
      ''] ++ (attrValues (mapAttrs makeAliasCommand cfg.aliases))))
    else
      (let makeAliasCommand = name: value: ''alias "${name}"="${value}"'';
      in (attrValues (mapAttrs makeAliasCommand cfg.aliases)))));
}