nuenv icon indicating copy to clipboard operation
nuenv copied to clipboard

Invoking an external script with Nix interpolation

Open srid opened this issue 2 years ago • 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.

srid avatar Apr 06 '23 13:04 srid

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

siph avatar Apr 11 '23 03:04 siph

@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.

lucperkins avatar Apr 26 '23 07:04 lucperkins

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.

hallettj avatar Jul 12 '24 06:07 hallettj

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

srid avatar Jul 12 '24 14:07 srid