Highly extensible software like Emacs, Vim, and Neovim tend to grow their own package managers. A software developer, for example, might want to install editor plugins that hook into a particular programming language's linter or language server. The programmer's text editor is therefore extended to support managing additional software to extend the text editor. If this loop continues for too long, the programmer's editor becomes more delicate and complex. The remedy for this problem is to manage software using dedicated tools apart from the programmer's editor itself, and the most powerful tool to do that in 2023 is Nix.
Put simply, using Nix and Home Manager allows users to declaratively configure their software in a reliable, reproducible, and largely self-documenting way. Once set up, a user can easily copy their configuration over to a new machine and get everything working quickly. Nix does have a learning curve, but climbing that curve is worth the effort.
To help newcomers try this, below is an example using Nix with Home Manager to configure Neovim without a Neovim-based plugin manager like packer.nvim or vim-plug. The following steps were tested on Debian 11:
-
Install Nix. For this guide, we are going to follow the single-user installation instructions:
$ sh <(curl -L https://nixos.org/nix/install) --no-daemon
-
Add the Home Manager Nix channel:
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager $ nix-channel --update
-
And then add this bit of configuration to your shell:
export NIX_PATH=$HOME/.nix-defexpr/channels:/nix/var/nix/profiles/per-user/root/channels${NIX_PATH:+:$NIX_PATH}
-
Install Home Manager:
$ nix-shell '<home-manager>' -A install
-
Edit the Home Manager configuration file found at
~/.config/nixpkgs/home.nix
. The default should look something like this:{ config, pkgs, ...}: { home.username = "test"; home.homeDirectory = "/home/test"; home.stateVersion = "22.11"; programs.home-manager.enable = true; } # Comments in this file were removed for brevity.
Use the Home Manager Option Search to find relevant configuration to add. Let's start with Neovim and git:
{ config, pkgs, ...}: { home.username = "test"; home.homeDirectory = "/home/test"; home.stateVersion = "22.11"; programs.home-manager.enable = true; programs.git.enable = true; programs.neovim.enable = true; }
-
Rebuild the Home Manager configuration:
$ home-manager switch
. This will either throw an error if the configuration file is errant, or spew a bunch of text and successfully install Neovim and git. -
Add more Neovim configuration. For this example, we want Neovim to be our default editor, and also be aliased to
vi
,vim
, andvimdiff
:{ config, pkgs, ...}: { home.username = "test"; home.homeDirectory = "/home/test"; home.stateVersion = "22.11"; programs.home-manager.enable = true; programs.git.enable = true; programs.neovim = { enable = true; defaultEditor = true; viAlias = true; vimAlias = true; vimdiffAlias = true; }; }
-
Rebuild the Home Manager configuration:
$ home-manager switch
. -
Add some plugins:
{ config, pkgs, ...}: { home.username = "test"; home.homeDirectory = "/home/test"; home.stateVersion = "22.11"; programs.home-manager.enable = true; programs.git.enable = true; programs.neovim = { enable = true; defaultEditor = true; viAlias = true; vimAlias = true; vimdiffAlias = true; plugins = with pkgs.vimPlugins; [ nvim-lspconfig nvim-treesitter.withAllGrammars plenary-nvim gruvbox-material mini-nvim ]; # Use the Nix package search engine to find # even more plugins : https://search.nixos.org/packages }; }
-
Rebuild the Home Manager configuration:
$ home-manager switch
. -
Not every Neovim plugin is already packaged in the Nix package repository, so let's write a little Nix function to help us download packages hosted on GitHub:
{ config, pkgs, lib, ...}:
let
fromGitHub = ref: repo: pkgs.vimUtils.buildVimPlugin {
pname = "${lib.strings.sanitizeDerivationName repo}";
version = ref;
src = builtins.fetchGit {
url = "https://github.com/${repo}.git";
ref = ref;
};
};
in
{
home.username = "test";
home.homeDirectory = "/home/test";
home.stateVersion = "22.11";
programs.home-manager.enable = true;
programs.git.enable = true;
programs.neovim = {
enable = true;
defaultEditor = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
plugins = with pkgs.vimPlugins; [
nvim-lspconfig
nvim-treesitter.withAllGrammars
plenary-nvim
gruvbox-material
mini-nvim
(fromGitHub "HEAD" "elihunter173/dirbuf.nvim")
];
};
}
- Rebuild the Home Manager configuration:
$ home-manager switch
.
Hopefully this is enough of an example to give a sense of how working with Nix and Home Manager is a significant improvement over configuring each application individually. Credit to Felix Breuer for that nice GitHub downloading function. There is much more to Nix and Home Manager then what was illustrated above, so please read their manuals, learn, explore, and enjoy.
Have you tried this out with a flake? The
fromGitHub
is precisely what I am looking for, but it results inerror: in pure evaluation mode, 'fetchTree' requires a locked input
.