/nvim-nix

Pierrot's Neovim flake

Primary LanguageLuaGNU General Public License v2.0GPL-2.0

My Neovim flake

This is my neovim configuration implemented as a flake. Thanks to the power of nix and flakes, my whole neovim configuration can be built with a single command.

Based on the template from kickstart-nix.nvim. If you come from this template, please know that I made some slights modifications a little.

Some of the features:

  • Neovim nightly.
  • LSPs, linters, formatters for Python.
  • Use Neorg for note taking.

Note: Many LSPs, formatters and others are not packaged in this flake. You have to provide them yourself. See this debate for more.

Themes

There are multiple themes available and you can activate a specific theme by passing the config.theme value to the nix package at build time. You can choose between the following themes:

You can also configure whether you want the background to be transparent or not using the config.transparentBackground value.

See ./nix/module.nix for the available option values.

Installation

Test drive

If you have Nix installed (with flakes enabled), you can test drive this by running:

nix run "github:pierrot-lc/nvim-nix"

NixOS and Home Manager (with flakes)

Add this flake to your NixOS flake inputs.

{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";

    nvim-nix = {
      url = "github:pierrot-lc/nvim-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    # ...
  };

  # ...
}

Using the overlay

Overlays are a way to provide additional packages to the list of available pkgs. This flake output such overlay to add our nvim-pkg derivation to pkgs. Here is a minimal example with home-manager:

# flake.nix
{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";

    nvim-nix = {
      url = "github:pierrot-lc/nvim-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs @ {
    self,
    nixpkgs,
    home-manager,
    ...
  }: let
    system = "x86_64-linux";
    lib = nixpkgs.lib;

    pkgs = import nixpkgs {
      inherit system;
      config = {
        allowUnfree = true;
      };
      overlays = [
        # We provide our `nvim-pkg` package by giving the overlay here.
        inputs.nvim-nix.overlays.${system}.default
      ];
    };
  in {
    homeConfigurations = {
      username = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        modules = [
          ./home.nix
        ];
      };
    };
  };
}
# home.nix
{pkgs, ...}: {
  home.packages = with pkgs; [
    nvim-pkg # This package will be found thanks to the added overlays.
  ];
}

Using the module

This flake also provide a module. It provides an interface to provide options before building the derivation. You can have a look into ./nix/module.nix to see the available options for yourself, along with their default values.

To make this work, you do not have to add this flake overlay but you have to provide the module. Here is a minimal example:

# flake.nix
{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";

    nvim-nix = {
      url = "github:pierrot-lc/nvim-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs @ {
    self,
    nixpkgs,
    home-manager,
    ...
  }: let
    system = "x86_64-linux";
    lib = nixpkgs.lib;

    pkgs = import nixpkgs {
      inherit system;
      config = {
        allowUnfree = true;
      };
    };
  in {
    homeConfigurations = {
      username = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        modules = [
          ./home.nix
          # Add the module here.
          inputs.nvim-nix.nixosModules.${system}.default
        ];
      };
    };
  };
}
# home.nix
{pkgs, ...}: {
  nvim-nix = {
    enable = true;
    theme = "gruvbox";
    transparentBackground = true;
  };
}

Philosophy

  • Manage plugins + external dependencies using Nix (managing plugins shouldn't be the responsibility of a plugin).
  • Configuration entirely in Lua1 (Vimscript is also possible). This makes it easy to migrate from non-nix dotfiles.
  • Usable on any device with Neovim and Nix installed.
  • Ability to create multiple derivations with different sets of plugins.
  • Use either nixpkgs or flake inputs as plugin source.
  • Use Neovim's built-in loading mechanisms.
  • Use Neovim's built-in LSP client.

Initialization order

This derivation creates an init.lua as follows:

  1. Add nvim/lua to the runtimepath.
  2. Add the content of nvim/init.lua.
  3. Add nvim/* to the runtimepath.
  4. Add nvim/after to the runtimepath.

This means that modules in nvim/lua can be required in init.lua and nvim/*/*.lua.

Modules in nvim/plugin/ are sourced automatically, as if they were plugins. Because they are added to the runtime path at the end of the resulting init.lua, Neovim sources them after loading plugins.

Bonus: bundle the neovim package into an executable

You can use nix-portable to bundle the derivation into a dependency-free executable.

nix bundle --bundler github:DavHau/nix-portable -o bundle

You still need nix to generate the bundle, but then you can simply pass around the generated ./bundle/bin/nvim wherever you want and execute your nvim package!

Make sure that the target machine has no conflicting nvim configuration. Have a look at ~/.config/nvim, ~/.local/share/nvim and ~/.local/state/nvim, and remove those directories if you have any conflict (make sure to make a backup before if you have important data there).

Footnotes

  1. The absence of a Nix module DSL for Neovim configuration is deliberate. If you were to copy the nvim directory to $XDG_CONFIG_HOME, and install the plugins, it would work out of the box.