Stuck writing my first package

I am trying to write an nvchad package as a way to learn nix and have got stuck. If you are not aware of nvchad you can think of it like a default set of configs for vim - installing is essentially done by installing neovim and then git clone https://github.com/NvChad/NvChad ~/.config/nvim --depth 1 and from there you configure it.

So far I have got Neovim configured and building using the following override:

{ lib, fetchFromGitHub, pkgs }:

let
  packages = [
    pkgs.ripgrep
    pkgs.gcc
    pkgs.sumneko-lua-language-server
  ];
in
  pkgs.neovim-unwrapped.overrideAttrs (oldAttrs: rec {
    pname = "neovim";
    version = "0.7.0";

    src = fetchFromGitHub {
      owner = "neovim";
      repo = "neovim";
      rev = "v${version}";
      sha256 = "03wh090acplj5kgrw87m6dh0rh5f71bg60s75qmqcsfjjwg1m1kr";
    };

    nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.makeWrapper pkgs.git];

    postInstall = ''
      makeWrapper "$out/bin/nvim" "$out/bin/nvchad"
      wrapProgram $out/bin/nvchad \
        --prefix PATH : ${lib.makeBinPath packages}
    '';
  })

My rough gameplan was to:

  1. Clone there repository somewhere (as per the nvchad instructions).
  2. Update the wrapper so that nvim launches using the XDG_CONFIG_HOME env var which would point at the nvchad directory cloned previously.

However I am unsure how to go about this so I’m reaching out to people more experienced in writing nix to get guidance on how to achieve this.

Looking forward to getting some guidance!

neovim 7 is on the Nixpkgs unstable branch, so you can use that instead of the override.

For nvchad, you can create a package using mkDerivation with neovim as an input and the nvchad repo as the src.

In the installPhase, copy everything in $src to something like $out/share/nvchad and symlink ${neovim}/bin/neovim to $out/bin/nvchad. Then, you can wrap nvchad and set the environment variable, (similar to how you set the PATH) to $out/share/nvchad.

Thanks @emmanuelrosa - makes much more sense.

I’ve attempted that but unfortunately it doesn’t look like you can call makeWrapper (or wrapProgram) on a symlinked file as I get the following error:

Builder called die: Cannot wrap '/nix/store/3wb0rjd0mdnn8b7a7bpkn9q128kq094g-nvchad-1.0/bin/.nvim' because it is not an executable file

nix derivation below:

{ stdenv, lib, pkgs, fetchFromGitHub}:

with lib;

let
in
  stdenv.mkDerivation rec {
    pname = "nvchad";
    version = "1.0";

    src = fetchFromGitHub {
      owner = "nvchad";
      repo = "nvchad";
      rev = "v${version}";
      sha256 = "08p9y19z6cfxsilljypp0bd74mxhi60s0vk202js6i1v9ml0rqsw";
    };

    buildInputs = [
      pkgs.makeWrapper
    ];

    installPhase = ''
      mkdir -p $out/bin
      ln -s ${pkgs.neovim}/bin/neovim $out/bin/.nvim
      makeWrapper "$out/bin/.nvim" "$out/bin/nvchad2"
    '';
  }
installPhase = ''
  mkdir -p $out/bin
  makeWrapper "${pkgs.neovim}/bin/neovim" "$out/bin/nvchad2"
'';

Might do the trick, since the wrapper just executes the binary in
question. But I know nothing about nvchad, and don’t understand why
you’re trying to symlink anything, so ignore me if this is silly :slight_smile:

Here’s a working example is shown below. I only played with it a bit, so expect some things not to work.

In a nutshell, a nvim is executed with a disposable configuration, wherein nvchad is set up. The config directory is not persistent in order to allow the package to update nvchad while also persisting the user’s custom configuration.

nvchad.nix

{ nixpkgs ? <nixpkgs> }:

let
  pkgs = import nixpkgs {} ;
  pname = "nvchad";
  version = "1.0";

  src = pkgs.fetchFromGitHub {
    owner = "nvchad";
    repo = "nvchad";
    rev = "v${version}";
    sha256 = "08p9y19z6cfxsilljypp0bd74mxhi60s0vk202js6i1v9ml0rqsw";
  };

  launcher = pkgs.writeScript "nvchad" ''
    export PATH="${pkgs.lib.makeBinPath [ pkgs.coreutils pkgs.neovim pkgs.ripgrep pkgs.fd pkgs.ueberzug ]}"
    export XDG_CONFIG_HOME=$(mktemp -d)

    # FIXME: Use the real XDG_CONFIG_HOME or fallback to $HOME/.config
    mkdir -p $HOME/.config/nvchad

    # Set up a disposable XDG_CONFIG_HOME
    mkdir $XDG_CONFIG_HOME/nvim
    ln -s ${src}/LICENSE $XDG_CONFIG_HOME/nvim/LICENSE
    ln -s ${src}/README.md $XDG_CONFIG_HOME/nvim/README.md
    ln -s ${src}/init.lua $XDG_CONFIG_HOME/nvim/init.lua
    cp -r ${src}/lua $XDG_CONFIG_HOME/nvim/lua
    chmod u+w $XDG_CONFIG_HOME/nvim/lua
    ln -s $HOME/.config/nvchad $XDG_CONFIG_HOME/nvim/lua/custom

    # Copy the initial user configuration, if it doesn't already exist.
    cp -n ${src}/lua/chadrc.lua $HOME/.config/nvchad/

    exec nvim "$@"
  '';
in
pkgs.stdenv.mkDerivation rec {
  inherit src version pname;

  installPhase = ''
    mkdir -p $out/bin
    ln -s ${launcher} $out/bin/nvchad
  '';
}
3 Likes