2025-07-31 12:37:19 +02:00
|
|
|
{
|
|
|
|
|
pkgs,
|
|
|
|
|
lib ? pkgs.lib,
|
|
|
|
|
config,
|
|
|
|
|
...
|
|
|
|
|
}: let
|
|
|
|
|
inherit (lib) mapAttrs mkOption types textClosureMap id attrNames;
|
|
|
|
|
mkNakedShell = pkgs.callPackage ./../utils/mkNakedShell.nix {};
|
|
|
|
|
|
|
|
|
|
addAttributeName = prefix:
|
|
|
|
|
mapAttrs (
|
|
|
|
|
k: v:
|
|
|
|
|
v
|
|
|
|
|
// {
|
|
|
|
|
text = ''
|
|
|
|
|
#### ${prefix}.${k}
|
|
|
|
|
${v.text}
|
|
|
|
|
'';
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
envBash =
|
|
|
|
|
pkgs.writeText "devshell-env.bash"
|
|
|
|
|
# sh
|
|
|
|
|
''
|
|
|
|
|
export DEVSHELL_DIR=@DEVSHELL_DIR@
|
|
|
|
|
# nicely handle it at the front or between/end
|
|
|
|
|
PATH=''${PATH#/path-not-set:}
|
|
|
|
|
PATH=''${PATH#:/path-not-set}
|
|
|
|
|
export PATH=$DEVSHELL_DIR/bin:$PATH
|
|
|
|
|
|
|
|
|
|
${textClosureMap
|
|
|
|
|
id
|
|
|
|
|
(addAttributeName "startup" config.enterShellCommands)
|
|
|
|
|
(attrNames config.enterShellCommands)}
|
|
|
|
|
|
|
|
|
|
# interactive session
|
|
|
|
|
if [[ $- == *i* ]]; then
|
|
|
|
|
true
|
|
|
|
|
${textClosureMap
|
|
|
|
|
id
|
|
|
|
|
(addAttributeName "interactive" config.interactiveShellCommands)
|
|
|
|
|
(attrNames config.interactiveShellCommands)}
|
|
|
|
|
fi # interactive session
|
|
|
|
|
|
|
|
|
|
unset DEVSHELL_DIR
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
entryType = types.submodule {
|
|
|
|
|
options = {
|
|
|
|
|
text = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
description = ''
|
|
|
|
|
Script to run.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
deps = mkOption {
|
|
|
|
|
type = types.listOf types.str;
|
|
|
|
|
default = [];
|
|
|
|
|
description = ''
|
|
|
|
|
A list of other steps that this one depends on.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
in {
|
|
|
|
|
options = {
|
|
|
|
|
shell = {
|
|
|
|
|
finalPackage = mkOption {
|
|
|
|
|
type = types.package;
|
|
|
|
|
internal = true;
|
|
|
|
|
};
|
|
|
|
|
finalProfile = mkOption {
|
|
|
|
|
type = types.package;
|
|
|
|
|
internal = true;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
name = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
default = "devshell";
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Name of the shell.
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
packages = mkOption {
|
|
|
|
|
type = types.listOf types.package;
|
|
|
|
|
default = [];
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Packages to install into the devshell.
|
|
|
|
|
'';
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
enterShellCommands = mkOption {
|
|
|
|
|
type = types.attrsOf entryType;
|
|
|
|
|
default = {};
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Commands to run when entering the shell.
|
|
|
|
|
'';
|
|
|
|
|
example = {
|
|
|
|
|
"hello".text = "echo Hello world";
|
|
|
|
|
};
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
interactiveShellCommands = mkOption {
|
|
|
|
|
type = types.attrsOf entryType;
|
|
|
|
|
default = {};
|
2025-08-21 13:46:24 +02:00
|
|
|
description = ''
|
|
|
|
|
Commands to run when entering an interactive shell.
|
|
|
|
|
'';
|
|
|
|
|
example = {
|
|
|
|
|
"hello".text = "echo Hello world";
|
|
|
|
|
};
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config.shell = {
|
|
|
|
|
finalProfile = pkgs.buildEnv {
|
|
|
|
|
name = "${config.name}-profile";
|
|
|
|
|
paths = config.packages;
|
|
|
|
|
postBuild = ''
|
|
|
|
|
substitute ${envBash} $out/env.bash --subst-var-by DEVSHELL_DIR $out
|
|
|
|
|
# NOTE: maybe also add an entrypoint shell script at $out/bin/devshell-${config.name}?
|
|
|
|
|
'';
|
|
|
|
|
meta.mainProgram = "devshell-${config.name}";
|
|
|
|
|
};
|
|
|
|
|
finalPackage = mkNakedShell {
|
2025-09-15 11:28:58 +02:00
|
|
|
inherit (config) name;
|
2025-07-31 12:37:19 +02:00
|
|
|
profile = config.shell.finalProfile;
|
2025-09-15 11:28:58 +02:00
|
|
|
passthru = {
|
|
|
|
|
metadata = config.meta.finalMetadata;
|
|
|
|
|
metadataJson = config.meta.finalJson;
|
|
|
|
|
};
|
2025-07-31 12:37:19 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|