22 Jun 2020

Better Nix setup for Spacemacs

In an earlier post I documented my setup for getting Spacemacs/Emacs to work with Nix. I've since found a much more elegant solution based on

No more Emacs packages for Nix and no need to defining functions that wrap executables in an invocation of nix-shell.

There's a nice bonus too, with this setup I don't need to run nix-shell, which always drops me at a bash prompt, instead I get a working setup in my shell of choice.

Setting up direnv

The steps for setting up direnv depends a bit on your setup, but luckily I found the official instructions for installing direnv to be very clear and easy to follow. There's not much I can add to that.

Setting up Spacemacs

Since emacs-direnv isn't included by default in Spacemacs I needed to do a bit of setup. I opted to create a layer for it, rather than just drop it in the list dotspacemacs-additional-packages. Yes, a little more complicated, but not difficult and I nurture an intention of submitting the layer for inclusion in Spacemacs itself at some point. I'll see where that goes.

For now, I put the following in the file ~/.emacs.d/private/layers/direnv/packages.el:

(defconst direnv-packages
      '(direnv))

(defun direnv/init-direnv ()
  (use-package direnv
    :init
    (direnv-mode)))

Setting up the project folders

In each project folder I then add the file .envrc containing a single line:

use_nix

Then I either run direnv allow from the command line, or run the function direnv-allow after opening the folder in Emacs.

Using it

It's as simple as moving into the folder in a shell – all required envvars are set up on entry and unset on exit.

In Emacs it's just as simple, just open a file in a project and the envvars are set. When switching to a buffer outside the project the envvars are unset.

There is only one little caveat, nix-build doesn't work inside a Nix shell. I found out that running

IN_NIX_SHELL= nix-build

does work though.

Tags: emacs nix spacemacs