DeterminateSystems/nuenv

Invoking an external script with Nix interpolation

srid opened this issue · 4 comments

srid commented

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.

siph commented

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)
  );
};

@srid Nushell itself is available in the scripts, so this, for example, should work:

{
  script = ''
    nu ${./nix-health.nu} ${system}
  '';
}

In terms of passing in system, @siph's approach is the only way I can think of that doesn't involve passing them as args in script.

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.

srid commented

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