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.
  5. Pre-fetch and pin any shortname plugins (see chapter 3).

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, ... }:
{
  # Configfuration items that should or must precede everything else, including
  # per-plugin pre-plugin-load configuration items
  earlyConfig = ''
    let mapleader = "\<Space>"
    augroup vimrc
      autocmd!
    augroup END
  '';
  # Configuration items that should be done prior to loading any plugins (but
  # don't depend on any single plugin); there is also `postPluginConfig` for
  # configuration items that should be done after loading *all* plugins.
  prePluginConfig = ''
    set termguicolors
    syntax enable
  '';
  # General configuration items that don't have any specific ordering
  # requirements; these are appended to the generated init.vim file, so 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 The Silver Searcher (ag) for search backend
    let g:ackprg = 'ag --nogroup --column'
    set grepprg:ag\ --nogroup\ --nocolor
    nnoremap <Leader>o :exe ':silent !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; [
    silver-searcher
    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

You can enable both pre-existing Nix vim plugin derivations (e.g. from nixpkgs), and vim plugins on github, both by using pluginRegistry.<pluginName>.enable.

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

{ config, lib, pkgs, ... }:
{
  pluginRegistry = {
    # In this case, the name 'ale' is automatically 'resolved' against
    # pkgs.vimPlugins to select the plugin source
    ale.enable = true;
    # In this case, `source` is explicitly pointed to an existing Vim plugin
    # derivation.
    "denite.nvim" = {
      enable = true;
      source = pkgs.vimPlugins.denite-nvim;
    };
    # In this case, the name fails to resolve against pkgs.vimPlugins, so
    # `source` is automatically inferred from the `name`, on the assumption
    # that it is a vim-plug-compatible 'shortname', which will be used to
    # dynamically construct a derivation from a Vim plugin sourced from
    # https://github.com/Shados/vim-session (see chapter 3).
    "Shados/vim-session".enable = true;
    vim-buffet = {
      enable = true;
      # In this case, we again are using a shortname for the source, but we set
      # it explicitly.
      source = "bagrat/vim-buffet";
      # Additionally, we specify the exact commit we want to pin and use for the git source.
      # Generally you are better off relying on the separate JSON pin files to
      # pin to a specific commit, but in this case the version after this
      # commit has breaking changes, which would mean the configuration of the
      # plugin would also have to change, meaning that the commit information
      # is more an element of configuration than of state. 'branch' and 'tag'
      # are also supported for specifying what to fetch.
      commit = "044f2954a5e49aea8625973de68dda8750f1c42d";
    };
    localPlugin = {
      enable = true;
      # In this case, Envy will dynamically construct a derivation using the
      # given Nix store path as the source.
      source = /some/local/path/or/store/path;
    };
    inDevPlugin = {
      enable = true;
      # 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.
      dir = "/a/local/path/string";
    };
  };
}

Specifying Dependencies

Envy allows for specifying a wide variety of dependency types:

{ config, lib, pkgs, ... }:
{
  pluginRegistry = {
    # Inter-plugin dependencies; the items should preferably be the names of
    # `pluginRegistry` or `vim.vimPlugins` items, but can alternatively be 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; [
      bash
      shellcheck
      shfmt
    ];
    # 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; [
      luafilesystem
    ];
    # 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.python2 = true;`.
    aPythonPlugin.remote.python2Deps = ps: with ps; [
      requests
    ];
  };
}

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
    vim-devicons.after = [
      "nerdtree" "vim-airline" "ctrlp-vim" "powerline/powerline" "denite-nvim"
      "unite-vim" "lightline-vim" "vim-startify" "vimfiler" "vim-flagship"
    ];
  };
}

Plugin Configuration

There are per-plugin versions of the earlyConfig, prePluginConfig, and postPluginConfig options under pluginRegistry.<pluginName>.nvimrc, named early, prePlugin, and postPlugin respectively. These are inserted into the generated neovim init.vim file immediately after or before the generic versions.