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
- direnv, and
- emacs-direnv
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.