2. Module Configuration

The full set of available configuration options is documented in Appendix A; this chapter serves as an overview of the configuration process and provides examples of how the options may be used.

Broadly, the process for configuring Envy is:

  1. Add non-plugin init.vim configuration.
  2. Enable the plugins you want to use.
  3. Specify any additional dependencies the plugins may have.
  4. Add per-plugin configuration.

Non-plugin Configuration

Adapt your non-plugin init.vim configuration to use Envy's module options.

By "non-plugin" here we mean specifically things that either don't depend on/configure any plugin, or that could depend on any one of several plugins (in which case, you should use Nix functionality to check which/whether any of those plugins are enabled and adapt the generated configuration appropriately).

Envy provides a wide array of options here, so some examples may be helpful:

{ config, lib, pkgs, ... }:
  # Configuration items that should be done prior to any per-plugin configuration
  prePluginConfig = ''
    let mapleader = "\<Space>"
    augroup vimrc
    augroup END
    set termguicolors
  # General configuration items that are appended to the end of the generated
  # vimrc. You can use e.g. `lib.mkAfter` if you need something to go at the
  # very end of the file.
  extraConfig = ''
    set incsearch
    set hlsearch
    set ignorecase
    set smartcase
    set number
    set relativenumber
    set autoindent
    set shiftwidth=2
    set softtabstop=2
    set tabstop=2
    set expandtab

    " Use Ripgrep (rg) for search backend
    let g:ackprg = '${pkgs.ripgrep}/bin/rg --vimgrep --smart-case --no-heading --max-filesize=4M'
    set grepprg:${pkgs.ripgrep}/bin/rg\ --vimgrep\ --smart-case\ --no-heading\ --max-filesize=4M

    nnoremap <Leader>o :exe ':silent !${pkgs.xdg-utils}/bin/xdg-open % &'<CR>
  # A list of packages whose executables should be added to the $PATH for
  # neovim. These will *only* be added to neovim's path, not to the system or
  # user profiles.
  extraBinPackages = with pkgs; [
    xdg_utils # xdg-open
  # See chapter 3
  mergePlugins = true;
  # `files` can be used to build a symlink tree of files and folders, which
  # would typically consist of any extra/local contents of .config/nvim/ in a
  # non-Nix neovim setup.
  files = {
    neosnippets.source = "/my/snippet/files/";

Enabling Plugins

There are several ways to specify the source for a plugin, depending on what you want:

{ config, lib, pkgs, ... }:
  pluginRegistry = {
    # In this case, `source` is pointed to an existing Vim plugin derivation.
    "denite.nvim" = {
      enable = true;
      source = pkgs.vimPlugins.denite-nvim;

    # In this case, Envy will dynamically construct a derivation using the
    # given Nix store path as the source.
    localPlugin = {
      enable = true;
      source = /some/local/path/or/store/path;

    # Here we instead instruct Envy to have Vim load the plugin from a local
    # filesystem path at run-time, rather than bundling it into the Nix store.
    # This is useful for doing plugin development, or if you otherwise want to
    # use a plugin outside of the Nix store, while still allowing you to
    # leverage Envy's configuration and dependency specification/resolution
    # mechanisms.
    inDevPlugin = {
      enable = true;
      dir = "/a/local/path/string";

    # Envy also provides a helper for constructing a vim plugin derivation from
    # a Niv sources.nix attrset, which you can then use as a source.
    vim-systemd-syntax = {
      enable = true;
      source = config.sn.programs.neovim.lib.buildVimPluginFromNiv (import ./pins { }) "vim-systemd-syntax";

Specifying Dependencies

Envy allows for specifying a wide variety of dependency types:

{ config, lib, pkgs, ... }:
  pluginRegistry = {
    # Inter-plugin dependencies; the items should either be `pluginRegistry`
    # attribute names or vim plugin derivations.
    neosnippet-snippets.dependencies = [ "neosnippet-vim" ];
    # Specifies that a plugin needs external executables from the given
    # packages made available in neovim's $PATH.
    ale.binDeps = with pkgs; [
    # Ensures that the specified Lua modules will be made available in
    # neovim's LUA_PATH/LUA_CPATH, meaning that the main neovim process can
    # load them for in-process Lua plugins and scripts to use.
    "Shados/precog.nvim".luaDeps = ps: with ps; [
    # Flags a plugin as being a 'remote' plugin requiring a plugin host for a
    # specific language (here, Python 3).
    denite-nvim.remote.python3 = true;
    # Pulls in plugin-host-language dependencies.
    # Automatically implies `remote.python3 = true;`.
    aPythonPlugin.remote.python3Deps = ps: with ps; [

Inter-plugin dependencies also determine the order in which Vim plugins are loaded at Vim run-time (by vim-plug).

There are additionally two "soft" dependency options (before and after, both of which take lists of plugin names only), that change how plugins are ordered if both are enabled, but does not cause the "dependency" to be enabled if the "dependent" plugin is, e.g.:

{ config, lib, pkgs, ... }:
  pluginRegistry = {
    # vim-devicons needs to be loaded after these plugins, if they
    # are being used, as per its installation guide.
    # Both `after` and `before` can be specified as either `pluginRegistry`
    # attribute names or vim plugin derivations.
    vim-devicons.after = [
      "nerdtree" "vim-airline" "ctrlp-vim" "powerline/powerline" "denite-nvim"
      "unite-vim" "lightline-vim" "vim-startify" "vimfiler" "vim-flagship"

It should be noted that lazy-loaded plugins don't fully respect ordering options, and don't trigger lazy-loading of dependencies. Either ensure dependencies aren't also being lazy-loaded, or put them behind the same lazy-load triggers as their dependents.

Plugin Configuration

There is a per-plugin version of the extraConfig option, under pluginRegistry.<pluginName>.extraConfig. These are inserted into the generated nvimrc after the prePluginConfig, before the top-level extraConfig, and in the same order plugins are loaded (that is, based on dependencies and explicit ordering information).