Giter Club home page Giter Club logo

nuenv's Introduction

Nuenv: an experimental Nushell environment for Nix

FlakeHub GitHub Actions status badge

Warning: This project is a fun experiment—and perhaps a source of inspiration for others—but not something you should use for any serious purpose.

This repo houses an example project that uses Nushell as an alternative builder for Nix (whose standard environment uses Bash). For more information, check out Nuenv: an experimental Nushell environment for Nix on the Determinate Systems blog.

Running the scenario

First, make sure that you have Nix installed with flakes enabled. We recommend using our Determinate Nix Installer:

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix \
  | sh -s -- install

With Nix installed, you can realise a Nix derivation:

nix build --print-build-logs

# Or without cloning this repo
nix build --print-build-logs "https://flakehub.com/f/DeterminateSystems/nuenv/*.tar.gz"

You should see build output like this:

hello-nix-nushell> >>> INFO
hello-nix-nushell> > Realising the hello-nix-nushell derivation for aarch64-darwin
hello-nix-nushell> > Using Nushell 0.77.0
hello-nix-nushell> > Declared build outputs:
hello-nix-nushell> + out
hello-nix-nushell> >>> SETUP
hello-nix-nushell> > Adding 1 package to PATH:
hello-nix-nushell> + hello-2.12.1
hello-nix-nushell> > Setting PATH
hello-nix-nushell> > Setting 1 user-supplied environment variable:
hello-nix-nushell> + MESSAGE = "Hello from Nix + Bash"
hello-nix-nushell> > Copying sources
hello-nix-nushell> > Creating output directories
hello-nix-nushell> >>> REALISATION
hello-nix-nushell> > Running build phase
hello-nix-nushell> + Running hello version 2.12.1
hello-nix-nushell> + Creating output directory at /nix/store/n0dqy5gpshz21hp1qhgj6795nahqpdyc-hello-nix-nushell/share
hello-nix-nushell> + Writing hello message to /nix/store/n0dqy5gpshz21hp1qhgj6795nahqpdyc-hello-nix-nushell/share/hello.txt
hello-nix-nushell> + Substituting Bash for Nushell in /nix/store/n0dqy5gpshz21hp1qhgj6795nahqpdyc-hello-nix-nushell/share/hello.txt
hello-nix-nushell> >>> DONE!
hello-nix-nushell> > out output written to /nix/store/n0dqy5gpshz21hp1qhgj6795nahqpdyc-hello-nix-nushell

This derivation does something very straightforward: it provides a message to GNU's hello tool and saves the result in a text file called hello.txt under the share directory.

cat ./result/share/hello.txt

How it works

The key differentiator from regular Nix here is that realisation happens in Nushell scripts rather than in Bash. The project's flake outputs a function called mkNushellDerivation that wraps Nix's built-in derivation function but, in contrast to stdenv.mkDerivation, uses Nushell as the builder, which in turn runs a builder.nu script that provides the Nix environment. In addition to builder.nu, env.nu provides helper functions to your realisation scripts.

Try it out

You can use nuenv to realise your own derivations. Here's a straightforward example:

{
  inputs = {
    nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2311.*.tar.gz";
    nuenv.url = "https://flakehub.com/f/DeterminateSystems/nuenv/*.tar.gz";
  };

  outputs = { self, nixpkgs, nuenv }: let
    overlays = [ nuenv.overlays.default ];
    systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
    forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f {
      inherit system;
      pkgs = import nixpkgs { inherit overlays system; };
    });
  in {
    packages = forAllSystems ({ pkgs, system }: {
      default = pkgs.nuenv.mkDerivation {
        name = "hello";
        src = ./.;
        inherit system;
        # This script is Nushell, not Bash
        packages = with pkgs; [ hello ];
        build = ''
          hello --greeting $"($env.MESSAGE)" | save hello.txt
          let out = $"($env.out)/share"
          mkdir $out
          cp hello.txt $out
        '';
        MESSAGE = "My custom Nuenv derivation!";
      };
    });
  };
}

To build and view the result of this derivation:

nix build
cat ./result/share/hello.txt

Creating Nushell scripts

Nuenv has a writeScriptBin function that you can use to wrap Nushell scripts using Nix. Here's an example:

# This example is only for x86_64-linux; adjust for your own platform
{
  inputs = {
    nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2311.*.tar.gz";
    nuenv.url = "https://flakehub.com/f/DeterminateSystems/nuenv/*.tar.gz";
  };

  outputs = { self, nixpkgs, nuenv }: let
    pkgs = import nixpkgs {
      system = "x86_64-linux";
      overlays = [ nuenv.overlays.nuenv ];
    };
  in {
    packages.x86_64-linux.run-me = pkgs.nuenv.writeScriptBin {
      name = "run-me";
      script = ''
        def blue [msg: string] { $"(ansi blue)($msg)(ansi reset)" }
        blue "Hello world"
      '';
    };
  };
}

writeScriptBin serves the same purpose as writeScriptBin in the Nixpkgs standard environment but for Nushell instead of Bash.

nuenv's People

Contributors

colemickens avatar flexiondotorg avatar hoverbear avatar lucperkins avatar mrfoxpro avatar notlebedev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nuenv's Issues

Thank you!

Hey, just want to say thank you for this!
for having had to work with bash in nix, this feels like the future.
my feeling is that bash is so entrenched in nix that it is to even introduce this into nixpkgs.
I really wish I could find a way to integrate this more in the ecosystem to give this project the support that it needs.

Make nushell a part of nix-nickels new shells ?

Just an idea here, writing it more for the purpose of discussing.
It seem nix nickel is trying to remake the basic nix building blocks with nickel.
Right now all of their shells are based on bash, could a continuation of this project live there ?

Dead code in build.nu

First time reading nu code, so I might be asking a dumb question here, but isn’t this whole if a no-op?

if not ($drv.initialPackages | is-empty) {

It seems that it prints stuff, but doesn’t actually add it to PATH?

Add LICENSE file

Currently this project has no license file, making it unclear if this is a project that is meant to be used or contributed to outside of DetSys.

Attribute `nuenv` missing on `pkgs` in the example flake

When running nix build on the example flake on the readme, nix build complains that pkgs.nuenv doesn't exist.

error: attribute 'nuenv' missing

       at /nix/store/sz6ip46qxi6rl4q6x41diwrj9f7rx42d-source/flake.nix:16:17:

           15|     packages = forAllSystems ({ pkgs, system }: {
           16|       default = pkgs.nuenv.mkDerivation {
             |                 ^
           17|         name = "hello";
       Did you mean one of naev, nodenv, nuXmv, nusmv or rbenv?

`nix run` returns empty record

Using the template at the bottom of the readme:

# This example is only for x86_64-linux; adjust for your own platform
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    nuenv.url = "github:DeterminateSystems/nuenv";
  };

  outputs = { self, nixpkgs, nuenv }: let
    pkgs = import nixpkgs {
      system = "x86_64-linux";
      overlays = [ nuenv.overlays.nuenv ];
    };
  in {
    packages.x86_64-linux.run-me = pkgs.nuenv.mkScript {
      name = "run-me";
      script = ''
        def blue [msg: string] { $"(ansi blue)($msg)(ansi reset)" }
        blue "Hello world"
      '';
    };
  };
}

Running both of these commands result in an empty record:

> nix run .#run-me
╭──────────────╮
│ empty record │
╰──────────────╯
> nix build .#run-me
> ./result/bin/run-me
╭──────────────╮
│ empty record │
╰──────────────╯

Passing the result into nushell works as expected:

> nu ./result/bin/run-me
Hello world

Nushell version: 0.77.1

Use the latest Nushell

Steps:

  • update to unstable nixpkgs with Nushell version 85
  • fix Nushell braking changes: replace 'let-env' with '$env'
  • nix build --print-build-logs

Result:
Run a derivation phase exit with error (or hangs when running with nu --log-lavel trace)

Invoking an external script with Nix interpolation

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.