2024-12-13-alternatives-to-the-nix-repl

Posted on December 13, 2024
Tags:

I am yet to find an ergonomic way to use the Nix repl. I’m sure it’s a great but I typically find myself needing to fiddle with Nix expressions over and over again sometimes before getting what I want and typing the code in a repl gets in my way. What if I need to change a function or a value.

Setting up a watcher

We can use an inotifywait loop to watch a file and execute it when it changes. Nix’s eval command can process an expression and that is all the main components we need for setting up a live Read Eval Process Loop. Just pass it the path to a file you want to evaluate. This particular command will evaluate an attribute called x. So you can have a bunch of Nix expressions in there and just move the one you want to evaluate at any moment to x.

 #!/usr/bin/env bash
 echo "watching..."
 while inotifywait -e close_write "$1"; do
 	nix eval --expr "builtins.getAttr \"x\" (import $(realpath "$1") { lib = (import <nixpkgs> {}).lib; })" --impure
 done

Note that for flake users to get <nixpkgs> to point to your store you need to setup it as your nix.nixPath. So define this value in your configuration somewhere and pass your nixpkgs reference to it.

Evaluation File

it should look something like this.


{ lib }:
{
  x =
    with lib;
    with builtins;
    let
      fonts = [
        { Hermit = "Hurmit"; }
        { Lekton = "Lekton"; }
        { AurulentSansMono = "AurulentSansM"; }
        { AnonymousPro = "AnonymicePro"; }
        { EnvyCodeR = "EnvyCodeR"; }
      ];

      generateFontTemplate = font_name: "family = ${font_name} Nerd Font";

      firstAttrName = z: head (attrNames z);
      firstAttrValue = z: head (attrValues z);
      mappedFonts = map (y: {
        name = "alacritty/fonts/${firstAttrName y}.toml";
        value = {
          text = generateFontTemplate (firstAttrValue y);
        };
      }) fonts;

    in

    listToAttrs mappedFonts;

}