Introduction

Version v0.9

Preface

What is nvf

nvf is a highly modular, configurable, extensible and easy to use Neovim configuration framework built and designed to be used with Nix. Boasting flexibility, robustness and ease of use, this projecct allows you to configure a fully featured Neovim instance with a few lines of Nix with lots of options for advanced users as well.

Try it out

Thanks to the portability of Nix, you can try out nvf without actually installing it to your machine. Below are the commands you may run to try out different configurations provided by this flake. As of v0.5, two specialized configurations are provided:

  • Nix (packages.nix) - Nix language server + simple utility plugins
  • Maximal (packages.maximal) - Variable language servers + utility and decorative plugins

You may try out any of the provided configurations using the nix run command on a system where Nix is installed.

$ cachix use nvf                   # Optional: it'll save you CPU resources and time
$ nix run github:notashelf/nvf#nix # Will run the default minimal configuration

Do keep in mind that this is susceptible to garbage collection meaning that the built outputs will be removed from your Nix store once you garbage collect.

Using Prebuilt Configs

$ nix run github:notashelf/nvf#nix
$ nix run github:notashelf/nvf#maximal

Available Configurations

Note

The below configurations are provided for demonstration purposes, and are not designed to be installed as is. You may refer to the installation steps below and the helpful tips section for details on creating your own configurations.

Nix

Nix configuration by default provides LSP/diagnostic support for Nix alongside a set of visual and functional plugins. By running nix run .#, which is the default package, you will build Neovim with this config.

$ nix run github:notashelf/nvf#nix test.nix
# => This will open a file called `test.nix` with Nix LSP and syntax highlighting

This command will start Neovim with some opinionated plugin configurations, and is designed specifically for Nix. the nix configuration lets you see how a fully configured Neovim setup might look like without downloading too many packages or shell utilities.

Maximal

Maximal is the ultimate configuration that will enable support for more commonly used language as well as additional complementary plugins. Keep in mind, however, that this will pull a lot of dependencies.

$ nix run github:notashelf/nvf#maximal -- test.nix
# => This will open a file called `test.nix` with a variety of plugins available

It uses the same configuration template with the Nix configuration, but supports many more languages, and enables more utility, companion or fun plugins.

Warning

Running the maximal config will download a lot of packages as it is downloading language servers, formatters, and more. If CPU time and bandwidth are concerns, please use the default package instead.

Installing nvf

There are multiple ways of installing nvf on your system. You may either choose the standalone installation method, which does not depend on a module system and may be done on any system that has the Nix package manager or the appropriate modules for NixOS and home-manager as described in the module installation section.

Standalone Installation

It is possible to install nvf without depending on NixOS or Home-Manager as the parent module system, using the neovimConfiguration function exposed in the extended library. This function will take modules and extraSpecialArgs as arguments, and return the following schema as a result.

{
  options = "The options that were available to configure";
  config = "The outputted configuration";
  pkgs = "The package set used to evaluate the module";
  neovim = "The built neovim package";
}

An example flake that exposes your custom Neovim configuration might look like

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nvf.url = "github:notashelf/nvf";
  };

  outputs = {nixpkgs, ...} @ inputs: {
    packages.x86_64-linux = {
      # Set the default package to the wrapped instance of Neovim.
      # This will allow running your Neovim configuration with
      # `nix run` and in addition, sharing your configuration with
      # other users in case your repository is public.
      default =
        (inputs.nvf.lib.neovimConfiguration {
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
          modules = [
            {
              config.vim = {
                # Enable custom theming options
                theme.enable = true;

                # Enable Treesitter
                treesitter.enable = true;

                # Other options will go here. Refer to the config
                # reference in Appendix B of the nvf manual.
                # ...
              };
            }
          ];
        })
        .neovim;
    };
  };
}

The above setup will allow to set up nvf as a standalone flake, which you can build independently from your system configuration while also possibly sharing it with others. The next two chapters will detail specific usage of such a setup for a package output in the context of NixOS or Home-Manager installation.

Standalone Installation on NixOS

Your built Neovim configuration can be exposed as a flake output to make it easier to share across machines, repositories and so on. Or it can be added to your system packages to make it available across your system.

The following is an example installation of nvf as a standalone package with the default theme enabled. You may use other options inside config.vim in configModule, but this example will not cover that extensively.

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    nvf.url = "github:notashelf/nvf";
  };

  outputs = {
    nixpkgs,
    nvf,
    self,
    ...
  }: {
    # This will make the package available as a flake output under 'packages'
    packages.x86_64-linux.my-neovim =
      (nvf.lib.neovimConfiguration {
        pkgs = nixpkgs.legacyPackages.x86_64-linux;
        modules = [
          # Or move this to a separate file and add it's path here instead
          # IE: ./nvf_module.nix
          (
            {pkgs, ...}: {
              # Add any custom options (and do feel free to upstream them!)
              # options = { ... };
              config.vim = {
                theme.enable = true;
                # and more options as you see fit...
              };
            }
          )
        ];
      })
      .neovim;

    # Example nixosConfiguration using the configured Neovim package
    nixosConfigurations = {
      yourHostName = nixpkgs.lib.nixosSystem {
        # ...
        modules = [
          # This will make wrapped neovim available in your system packages
          # Can also move this to another config file if you pass your own
          # inputs/self around with specialArgs
          ({pkgs, ...}: {
            environment.systemPackages = [self.packages.${pkgs.stdenv.system}.neovim];
          })
        ];
        # ...
      };
    };
  };
}

Standalone Installation on Home-Manager

Your built Neovim configuration can be exposed as a flake output to make it easier to share across machines, repositories and so on. Or it can be added to your system packages to make it available across your system.

The following is an example installation of nvf as a standalone package with the default theme enabled. You may use other options inside config.vim in configModule, but this example will not cover that extensively.

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    nvf.url = "github:notashelf/nvf";
  };

  outputs = {nixpkgs, home-manager, nvf, ...}: let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
    configModule = {
      # Add any custom options (and do feel free to upstream them!)
      # options = { ... };

      config.vim = {
        theme.enable = true;
        # and more options as you see fit...
      };
    };

    customNeovim = nvf.lib.neovimConfiguration {
      inherit pkgs;
      modules = [configModule];
    };
  in {
    # This will make the package available as a flake output under 'packages'
    packages.${system}.my-neovim = customNeovim.neovim;

    # Example Home-Manager configuration using the configured Neovim package
    homeConfigurations = {
      "your-username@your-hostname" = home-manager.lib.homeManagerConfiguration {
        # ...
        modules = [
          # This will make Neovim available to users using the Home-Manager
          # configuration. To make the package available to all users, prefer
          # environment.systemPackages in your NixOS configuration.
          {home.packages = [customNeovim.neovim];}
        ];
        # ...
      };
    };
  };
}

Module Installation

The below chapters will describe installing nvf as NixOS and Home-Manager modules. Note that those methods are mutually exclusive, and will likely cause path collisions if used simultaneously.

NixOS Module

The NixOS module allows us to customize the different vim options from inside the NixOS configuration without having to call for the wrapper yourself. It is the recommended way to use nvf alongside the home-manager module depending on your needs.

With Flakes

Prerequisites

To install nvf with flakes, you must make sure the following requirements are met.

  1. Nix 2.4 or later must be installed. You may use nix-shell to get a later version of Nix from nixpkgs.
  2. Flake-related experimental features must be enabled. Namely, you need nix-command and flakes. Some Nix vendors enable those by default, please consult their documentation if you are not using mainstream Nix.
    • When using NixOS, add the following to your configuration.nix and rebuild your system.

      nix.settings.experimental-features = "nix-command flakes";
    • If you are not using NixOS, add the following to nix.conf (located at ~/.config/nix/ or /etc/nix/nix.conf).

      experimental-features = nix-command flakes
    • You may need to restart the Nix daemon with, for example, sudo systemctl restart nix-daemon.service.

    • Alternatively, you can enable flakes on a per-command basis with the following additional flags to nix and home-manager:

      $ nix --extra-experimental-features "nix-command flakes" <sub-commands>

Usage

To use nvf with flakes, we first need to add the input to our flake.nix.

# flake.nix
{
  inputs = {
    # Optional, if you intend to follow nvf's obsidian-nvim input
    # you must also add it as a flake input.
    obsidian-nvim.url = "github:epwalsh/obsidian.nvim";

    # Required, nvf works best and only directly supports flakes
    nvf = {
      url = "github:NotAShelf/nvf";
      # You can override the input nixpkgs to follow your system's
      # instance of nixpkgs. This is safe to do as nvf does not depend
      # on a binary cache.
      inputs.nixpkgs.follows = "nixpkgs";
      # Optionally, you can also override individual plugins
      # for example:
      inputs.obsidian-nvim.follows = "obsidian-nvim"; # <- this will use the obsidian-nvim from your inputs
    };

    # ...
  };
}

Followed by importing the NixOS module somewhere in your configuration.

{
  # assuming nvf is in your inputs and inputs is in the argset
  # see example below
  imports = [ inputs.nvf.nixosModules.default ];
}

Example Installation

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nvf.url = "github:notashelf/nvf";
  };

  outputs = { nixpkgs, nvf, ... }: {
    # ↓ this is your host output in the flake schema
    nixosConfigurations."your-hostname" = nixpkgs.lib.nixosSystem {
      modules = [
        nvf.nixosModules.default # <- this imports the NixOS module that provides the options
        ./configuration.nix # <- your host entrypoint, `programs.nvf.*` may be defined here
      ];
    };
  };
}

Once the module is properly imported by your host, you will be able to use the programs.nvf module option anywhere in your configuration in order to configure nvf.

{
  programs.nvf = {
    enable = true;
    
    # Your settings need to go into the settings attribute set
    # most settings are documented in the appendix
    settings = {
      vim.viAlias = false;
      vim.vimAlias = true;
      vim.lsp = {
        enable = true;
      };
    };
  };
}

Note

nvf exposes a lot of options, most of which are not referenced in the installation sections of the manual. You may find all available options in the appendix

Without Flakes

As of v0.8, it is possible to install nvf on a system if you are not using flakes. This is possible thanks to the flake-compat project.

To get started, you must fetch the repository using builtins.fetchTarball or a similar mechanism.

# configuration.nix
let
  nvf = import (builtins.fetchTarball {
    url = "https://github.com/notashelf/nvf/archive/<commit or tag>.tar.gz";
    # Optionally, you can add 'sha256' for verification and caching
    # sha256 = "<sha256>";
  });
in {
  imports = [
    # Import the NixOS module from your fetched input
    nvf.nixosModules.nvf
  ];

  # Once the module is imported, you may use `programs.nvf` as exposed by the
  # NixOS module.
  programs.nvf.enable = true;
}

Tip

Nix2 does not have a builtin lockfile mechanism like flakes. As such you must manually update the URL and hash for your input. This is annoying to deal with, and most users choose to defer this task to projects such as npins or niv. If you are new to NixOS, I encourage you to look into Flakes and see if they fit your use case. Alternatively, look into the aforementioned projects for more convenient dependency management mechanisms.

# Home-Manager Module {#ch-hm-module}

The home-manager module allows us to customize the different vim options from inside the home-manager configuration without having to call for the wrapper yourself. It is the recommended way to use nvf alongside the NixOS module depending on your needs.

With Flakes

Prerequisites

To install nvf with flakes, you must make sure the following requirements are met.

  1. Nix 2.4 or later must be installed. You may use nix-shell to get a later version of Nix from nixpkgs.
  2. Flake-related experimental features must be enabled. Namely, you need nix-command and flakes. Some Nix vendors enable those by default, please consult their documentation if you are not using mainstream Nix.
    • When using NixOS, add the following to your configuration.nix and rebuild your system.

      nix.settings.experimental-features = "nix-command flakes";
    • If you are not using NixOS, add the following to nix.conf (located at ~/.config/nix/ or /etc/nix/nix.conf).

      experimental-features = nix-command flakes
    • You may need to restart the Nix daemon with, for example, sudo systemctl restart nix-daemon.service.

    • Alternatively, you can enable flakes on a per-command basis with the following additional flags to nix and home-manager:

      $ nix --extra-experimental-features "nix-command flakes" <sub-commands>

Usage

To use nvf with flakes, we first need to add the input to our flake.nix.

# flake.nix
{
  inputs = {
    # Optional, if you intend to follow nvf's obsidian-nvim input
    # you must also add it as a flake input.
    obsidian-nvim.url = "github:epwalsh/obsidian.nvim";

    # Required, nvf works best and only directly supports flakes
    nvf = {
      url = "github:NotAShelf/nvf";
      # You can override the input nixpkgs to follow your system's
      # instance of nixpkgs. This is safe to do as nvf does not depend
      # on a binary cache.
      inputs.nixpkgs.follows = "nixpkgs";
      # Optionally, you can also override individual plugins
      # for example:
      inputs.obsidian-nvim.follows = "obsidian-nvim"; # <- this will use the obsidian-nvim from your inputs
    };

    # ...
  };
}

Followed by importing the home-manager module somewhere in your configuration.

{
  # Assuming "nvf" is in your inputs and inputs is in the argument set.
  # See example installation below
  imports = [ inputs.nvf.homeManagerModules.default ];
}

Example Installation

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    nvf.url = "github:notashelf/nvf";
  };

  outputs = { nixpkgs, home-manager, nvf, ... }: {
    # ↓ this is your home output in the flake schema, expected by home-manager
    "your-username@your-hostname" = home-manager.lib.homeManagerConfiguration {
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      modules = [
        nvf.homeManagerModules.default # <- this imports the home-manager module that provides the options
        ./home.nix # <- your home entrypoint, `programs.nvf.*` may be defined here
      ];
    };
  };
}

Once the module is properly imported by your host, you will be able to use the programs.nvf module option anywhere in your configuration in order to configure nvf.

{
  programs.nvf = {
    enable = true;
    # your settings need to go into the settings attribute set
    # most settings are documented in the appendix
    settings = {
      vim.viAlias = false;
      vim.vimAlias = true;
      vim.lsp = {
        enable = true;
      };
    };
  };
}

Note

nvf exposes a lot of options, most of which are not referenced in the installation sections of the manual. You may find all available options in the appendix

Without Flakes

As of v0.8, it is possible to install nvf on a system if you are not using flakes. This is possible thanks to the flake-compat project.

To get started, you must fetch the repository using builtins.fetchTarball or a similar mechanism.

# home.nix
let
  nvf = import (builtins.fetchTarball {
    url = "https://github.com/notashelf/nvf/archive/<commit or tag>.tar.gz";
    # Optionally, you can add 'sha256' for verification and caching
    # sha256 = "<sha256>";
  });
in {
  imports = [
    # Import the NixOS module from your fetched input
    nvf.homeManagerModules.nvf
  ];

  # Once the module is imported, you may use `programs.nvf` as exposed by the
  # NixOS module.
  programs.nvf.enable = true;
}

Tip

Nix2 does not have a builtin lockfile mechanism like flakes. As such you must manually update the URL and hash for your input. This is annoying to deal with, and most users choose to defer this task to projects such as npins or niv. If you are new to NixOS, I encourage you to look into Flakes and see if they fit your use case. Alternatively, look into the aforementioned projects for more convenient dependency management mechanisms.