2025-07-31 12:37:19 +02:00
|
|
|
{
|
|
|
|
|
lib,
|
|
|
|
|
pkgs,
|
|
|
|
|
config,
|
|
|
|
|
...
|
|
|
|
|
}: let
|
2025-09-15 15:37:32 +02:00
|
|
|
inherit
|
|
|
|
|
(lib)
|
|
|
|
|
filter
|
|
|
|
|
filterAttrs
|
|
|
|
|
assertMsg
|
|
|
|
|
head
|
|
|
|
|
length
|
|
|
|
|
escapeShellArg
|
|
|
|
|
types
|
|
|
|
|
mkOption
|
|
|
|
|
concatStringsSep
|
|
|
|
|
;
|
2025-07-31 12:37:19 +02:00
|
|
|
|
|
|
|
|
envToBash = {
|
|
|
|
|
name,
|
|
|
|
|
value,
|
|
|
|
|
eval,
|
|
|
|
|
prefix,
|
|
|
|
|
...
|
|
|
|
|
} @ args: let
|
2025-09-15 13:10:48 +02:00
|
|
|
vals = filter (key: args.${key} != null && args.${key} != false) [
|
2025-07-31 12:37:19 +02:00
|
|
|
"eval"
|
|
|
|
|
"prefix"
|
|
|
|
|
"unset"
|
|
|
|
|
"value"
|
|
|
|
|
];
|
|
|
|
|
valType = head vals;
|
|
|
|
|
in
|
|
|
|
|
assert assertMsg (
|
|
|
|
|
(length vals) > 0
|
|
|
|
|
) "[devshell/env]: ${name} expected one of (value|eval|prefix|unset) to be set.";
|
|
|
|
|
assert assertMsg ((length vals) < 2)
|
|
|
|
|
"[devshell/env]: ${name} expected only one of (value|eval|prefix|unset) to be set. Not ${toString vals}";
|
|
|
|
|
assert assertMsg (!(name == "PATH" && valType == "value")) "[devshell/env]: ${name} should not override the value. Use 'prefix' instead.";
|
|
|
|
|
if valType == "value"
|
|
|
|
|
then "export ${name}=${escapeShellArg (toString value)}"
|
|
|
|
|
else if valType == "eval"
|
|
|
|
|
then "export ${name}=${eval}"
|
|
|
|
|
else if valType == "prefix"
|
|
|
|
|
then ''export ${name}=$(${pkgs.coreutils}/bin/realpath --canonicalize-missing "${prefix}")''${${name}+:''${${name}}}''
|
|
|
|
|
else if valType == "unset"
|
|
|
|
|
then ''unset ${name}''
|
|
|
|
|
else throw "[devshell] BUG in the env module. This should never be reached.";
|
|
|
|
|
|
2025-09-15 15:37:32 +02:00
|
|
|
envType = types.submodule ({
|
|
|
|
|
config,
|
|
|
|
|
name,
|
|
|
|
|
...
|
|
|
|
|
}: {
|
2025-07-31 12:37:19 +02:00
|
|
|
options = {
|
|
|
|
|
name = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
default = name;
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Name of the environment variable, usually already set to `<name>`.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2025-09-15 15:37:32 +02:00
|
|
|
description = mkOption {
|
2025-08-21 13:46:24 +02:00
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
|
|
|
|
Description of the env var, can be shown in the menu.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
visible = mkOption {
|
|
|
|
|
type = types.bool;
|
2025-09-15 15:37:32 +02:00
|
|
|
default = config.description != null;
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Whether to include this env var and it's description in the menu.
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
value = mkOption {
|
|
|
|
|
type = with types;
|
|
|
|
|
nullOr (oneOf [
|
|
|
|
|
str
|
|
|
|
|
int
|
|
|
|
|
bool
|
|
|
|
|
package
|
|
|
|
|
]);
|
|
|
|
|
default = null;
|
2025-08-21 13:46:24 +02:00
|
|
|
example = "hello";
|
|
|
|
|
description = ''
|
|
|
|
|
Any value to convert to a string and set the env variable to.
|
|
|
|
|
There is no evaluation of the value, for that see [eval](#envnameeval).
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
eval = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
2025-08-21 13:46:24 +02:00
|
|
|
Like value but evaluated by Bash. This allows to inject other
|
2025-07-31 12:37:19 +02:00
|
|
|
variable names or even commands using the `$()` notation.
|
|
|
|
|
'';
|
|
|
|
|
example = "$OTHER_VAR";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
prefix = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
|
|
|
|
Prepend to PATH-like environment variables.
|
|
|
|
|
|
2025-08-21 13:46:24 +02:00
|
|
|
For example `name = "PATH"; prefix = "bin";` will expand the path of
|
|
|
|
|
`./bin` and prepend it to the `PATH`, separated by `:`.
|
2025-07-31 12:37:19 +02:00
|
|
|
'';
|
|
|
|
|
example = "bin";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
unset = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Unset the env variable.
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
in {
|
|
|
|
|
options.env = mkOption {
|
|
|
|
|
type = types.attrsOf envType;
|
|
|
|
|
default = {};
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Manage environment variables.
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = {
|
|
|
|
|
env = {
|
|
|
|
|
"XDG_DATA_DIRS".eval = "$DEVSHELL_DIR/share:\${XDG_DATA_DIRS-}";
|
|
|
|
|
};
|
2025-09-15 15:37:32 +02:00
|
|
|
enterShellCommands."env".text =
|
|
|
|
|
concatStringsSep "\n" (map envToBash (builtins.attrValues config.env));
|
|
|
|
|
# meta entries for the menu
|
|
|
|
|
meta.entries = builtins.mapAttrs (_name: env: {
|
|
|
|
|
inherit (env) description;
|
|
|
|
|
section = "Environment Variables";
|
|
|
|
|
}) (filterAttrs (_name: env: env.visible) config.env);
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
}
|