Invoking an external script with Nix interpolation
srid opened this issue · 4 comments
I feel like this is a bit of a hack,
https://github.com/srid/nix-health/blob/0c4735b6403a4fd13ef170f3c21296e05cd32fe5/flake.nix#L21
packages.default = pkgs.nuenv.mkScript {
name = "nix-health";
script = ''
${lib.getExe pkgs.nushell} ${./nix-health.nu} ${system}
'';
}
nix-health.nu
references the system
variable, so I'm passing it as a command-line argument. Also, I have to manually pull in pkgs.nushell
to invoke the script. Is there a more idiomatic way of achieving this? The main goal is to put the script
body in a separate file, whilst still being able to reference Nix variables in scope.
This is still hacky!
You can use substituteAll
to replace string instances inside of a file surrounding the replacement targets with @
, eg:
foo = pkgs.substituteAll {
name = "foo.nu";
src = ./foo.nu;
system = "${system}";
nushell = "${pkgs.nushell}";
nix-health = "${./nix-health.nu}";
}
#foo.nu
@nushell@ @nix-health@ @system@
However, I'm not sure of an elegant way to plug the resulting file into the script
value.
Instead you can reuse the same syntax and just use replaceStrings
directly on the file contents:
foo = pkgs.nuenv.mkScript {
name = "foo";
script = (builtins.replaceStrings
[ "@system@" "@nushell@" "@nix-health@ ]
[ "${system}" "${pkgs.nushell}" "${./nix-health.nu}" ]
(builtins.readFile ./foo.nu)
);
};
I pushed PR #27 which adds nuenv.writeShellApplication
. That accepts runtimeInputs
which sets environment variables in the script. Using that feature I think you could do it like this:
packages.default = pkgs.nuenv.writeShellApplication {
name = "nix-health";
runtimeEnv = { inherit system };
text = builtins.readFile ./nix-health.nu;
};
Then in nix-health.nu
you would access system as $env.system
.
I pushed PR #27 which adds
nuenv.writeShellApplication
.
Great! I'll see if I can use that to replace this:
https://github.com/srid/nixos-flake/blob/cab6539d198792f94fbac029e5a63523604fd172/nix/nu.nix#L4-L7