Nuenv - now revived!

New project: GitHub - xav-ie/nuenv: A Nushell environment for Nix - revived! :coffin:

Last year, GitHub - DeterminateSystems/nuenv: A Nushell environment for Nix was archived :cry:. Nuenv enabled writeShellApplication to use Nushell wrappers instead of Bash.

Nushell is great and I find I can work far faster with it than any Python, Bash, or Node script I write. I love the expressiveness and ease. You can learn more about it here: https://nushell.sh.

Fortunately, the original project encourages forks and the license is MIT. I’ve made enough local changes to my writeNuApplication copy that I decided to publish an update.

Notable improvements:

It’s still a baby and I mainly migrated my updates and got basic CI working. If you write any Nushell, please consider contributing so we can all benefit :hugs:. Technical feedback welcome through GitHub issues!

17 Likes

Just yesterday I was looking for something like this​:fire::tada:.

Btw, just wondering how this differs from using,
pkgs.writers.wrtieNuBin?
:thinking:
I see that this Nuenv have builInputs kind of attributes.
But functionality wise anything different?
When I should go for these compared to writers?:thinking:

Hm, I was not aware of writeNuBin… that definitely makes some of the project obsolete!

I mostly only use writeNuApplication, which allows you to specify runtimeInputs without having to write lib.getExe or ${derivation}/bin/${name} everywhere. It also allows specifying runtimeEnv, which I find very useful.

writeNuBin or any write*Bin writers are kind of cumbersome to use for any script that has lots of deps or is greater than ~10 lines.

I will have to see how this writeNuBin affects things and simplify the project. Thanks for bringing that to my attention.

2 Likes

Whatever you end up doing, I would find it most convenient in Nixpkgs. I should really start using one of these instead of writeShellApplication everywhere.

4 Likes

also of relevance and use:

1 Like

I did not know this was an option… I was under impression for some reason this was unwanted. I would also prefer it there.

I will try and fix this up and make a pr for the writeNuApplication soon. :smiley:

Ooh, this seems way more powerful. I only created this project again mainly to get writeNuApplication back, but maybe this project will be closed again due to these other cool projects. I will have to see how this affects things. Thank you.

2 Likes

If you’re doing that, I should add writeFishApplication too.

If it looks like we are going to be adding more write*Application, maybe we should instead have writeShellApplication have an optional setting for the shell to use, and some conditional logic for what checkers to use based on that?

3 Likes

Also just a demo script setup for Bash using writers. Improved the readability, so I’ll just touch the name, dependencies, script there.

Maybe we can bring a common wrapperArgs like that?
But too many functions out there, we want a common pattern here.
Like a universal function with args like:

name
Interpreter
extraArgs
packages
script

And making default values, template examples will help unify things.

At work we migrated all our scripts to nushell and also created a writeNuApplication wrapper as we migrated from writeShellApplication and missed some of the features in writeNuBin.

Some notable features are to inject environment variables as well as support nushell modules where common functions/tooling could be included.

Here is the source:

{
  lib,
  symlinkJoin,
  writers,
  nushell,
}:

{
  name,
  text,
  modules ? [ ],
  runtimeInputs ? [ ],
  runtimeEnv ? null,
}:

let
  modulesDrv = symlinkJoin {
    name = "modules";
    paths = modules;
  };

  interpreterArgs = [
    "--no-config-file"
  ]
  ++ (lib.optional (modules != [ ]) "--include-path=${modulesDrv}");

  setEnvWrapperArgs = lib.pipe runtimeEnv [
    (lib.mapAttrsToList (
      name: value: [
        "--set"
        name
        value
      ]
    ))
    lib.flatten
  ];
in
writers.makeScriptWriter {
  interpreter = "${lib.getExe nushell} ${lib.concatStringsSep " " interpreterArgs}";
  makeWrapperArgs =
    lib.optionals (runtimeInputs != [ ]) [
      "--prefix"
      "PATH"
      ":"
      (lib.makeBinPath runtimeInputs)
    ]
    ++ lib.optionals (runtimeEnv != null) setEnvWrapperArgs;
} "/bin/${name}" text

Usage could look something like this:

{
  writeNuApplication,
  # Runtime
  google-cloud-sdk,
  kubectl,
  nushell-modules,
}:

writeNuApplication {
  name = "mesh-cert-status-test";

  modules = [
    nushell-modules.k8s
  ];

  runtimeInputs = [
    (google-cloud-sdk.withExtraComponents [
      google-cloud-sdk.components.gke-gcloud-auth-plugin
    ])
    kubectl
  ];

  text = builtins.readFile ./main.nu;
}
2 Likes

That is really cool and exactly the type of thing I want to do in the near future. Thank you. I will try to integrate something like this probably in the next month. I am out for a few weeks.