Vim

From NixOS Wiki
Revision as of 21:46, 7 June 2020 by imported>Louwers (Delete VAM section (abandoned))

Installation

Basic Install

  environment.systemPackages = with pkgs; [ vim ];

or

  environment.systemPackages = with pkgs; [ vim_configurable ];

Using Home Manager

Vim can easily be set up using Home Manager. Here's a minimal example:

  programs.vim = {
    enable = true;
    plugins = [ "vim-airline" ];
    settings = { ignorecase = true; };
    extraConfig = ''
      set mouse=a
    '';
  };

See [1] for the full set of options.

Custom setup without using Home Manager

Note: To get a general overview about how to set up your vim in nix, refer to mpscholten's blog

Vim plugins can be installed with the help of nix. You can omit using vim plugin managers and do everything in your .nixpkgs/config.

A lot of documentation about package management and configuration of vim in nix is stored at vim-utils.nix in nixpkgs.

Customizations

Both vim and neovim can be further configured to include your favorite plugins and additional libraries. To list all available vim plugins, run nix search nixpkgs.vimPlugins.

Add the following code to your ~/.nixpkgs/config.nix:

{
  packageOverrides = pkgs: with pkgs; {
    myVim = vim_configurable.customize {
      name = "vim-with-plugins";
      # add here code from the example section
    }
    myNeovim = neovim.override {
      configure = {
        customRC = ''
          # here your custom configuration goes!
        '';
        packages.myVimPackage = with pkgs.vimPlugins; {
          # see examples below how to use custom packages
          start = [ ];
          opt = [ ];
        };      
    }
  }
}

After that you can install your special grafted `myVim` or `myNeovim` packages.

Examples

Apply custom vimrc configuration

vim_configurable.customize {
  name = "vim-with-plugins";
  # add custom .vimrc lines like this:
  vimrcConfig.customRC = ''
    set hidden
    set colorcolumn=80 
  '';
}

Using vim's builtin packaging capability

vim_configurable.customize {
  vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
    # loaded on launch
    start = [ youcompleteme fugitive ];
    # manually loadable by calling `:packadd $plugin-name`
    opt = [ phpCompletion elm-vim ];
    # To automatically load a plugin when opening a filetype, add vimrc lines like:
    # autocmd FileType php :packadd phpCompletion
  }
};

Using Pathogen as manager

There is a pathogen implementation as well, but its startup is slower and [VAM] has more features.

vimrcConfig.pathogen.knownPlugins = vimPlugins; # optional
vimrcConfig.pathogen.pluginNames = [ "vim-addon-nix" "youcompleteme" ];

Using Vim-Plug as manager

vimrcConfig.plug.plugins = with pkgs.vimPlugins; [vim-addon-nix youcompleteme];

Adding new plugins

As per the instructions found in https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/vim.section.md

  • First run ./update.py.
  • Commit the changes with the commit message "vimPlugins: Update".
  • Add your plugin to ./vim-plugin-names (please try to maintain the list alphabetically sorted).
  • Run ./update.py once again to generate the plugin's nix expression.
  • Commit your changes one more time, this time with the message formated as such: "vimPlugins.[plugin-name]: init at [version]".
  • If you need to add additional code/patches to the generated code, add those lines to pkgs/misc/vim-plugins/vim2nix/additional-nix-code and rerun ./update.py. They will be included in the generated code.

Notes Regarding Plugins

For additional info, you may wish to check https://github.com/NixOS/nixpkgs/tree/master/pkgs/misc/vim-plugins .

Add a new custom plugin to the users packages

Sometimes you do not want to change upstream plugins, for this you can use vimrcConfig.vam.knownPlugins and vimrcConfig.vam.pluginDirectories like this:

let
  customPlugins.vim-better-whitespace = pkgs.vimUtils.buildVimPlugin {
    name = "vim-better-whitespace";
    src = pkgs.fetchFromGitHub {
      owner = "ntpeters";
      repo = "vim-better-whitespace";
      rev = "984c8da518799a6bfb8214e1acdcfd10f5f1eed7";
      sha256 = "10l01a8xaivz6n01x6hzfx7gd0igd0wcf9ril0sllqzbq7yx2bbk";
    };
  };

in {
   users.users.<yourNickname>.packages = [
    (pkgs.vim_configurable.customize {
      name = "vim";
      vimrcConfig.vam.knownPlugins = pkgs.vimPlugins // customPlugins;
      vimrcConfig.vam.pluginDictionaries = [ 
        { names = "vim-better-whitespace" ]; } ]
    })
};

Vim as a Python IDE

The following snippet will make a full featured python IDE:

vim_configurable.customize {
  vimrcConfig = {
    customRC = ''
      let g:LanguageClient_serverCommands = {
        \ 'python': ['pyls']
        \ }
       nnoremap <F5> :call LanguageClient_contextMenu()<CR>
       nnoremap <silent> gh :call LanguageClient_textDocument_hover()<CR>
       nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>
       nnoremap <silent> gr :call LanguageClient_textDocument_references()<CR>
       nnoremap <silent> gs :call LanguageClient_textDocument_documentSymbol()<CR>
       nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
       nnoremap <silent> gf :call LanguageClient_textDocument_formatting()<CR>
    '';
    packages.myVimPackage = with pkgs.vimPlugins; {
      start = [ LanguageClient-neovim ];
    }
};

Then put the following expression in environment.systemPackages or in the home-manager package list, to install python-language-server:

(python3.withPackages(ps: [
  ps.python-language-server
  # the following plugins are optional, they provide type checking, import sorting and code formatting
  ps.pyls-mypy ps.pyls-isort ps.pyls-black
]))

Real life examples

YouCompleteMe

Currently the youcompleteme plugin uses unwrapped clang on linux. This causes it to not find stdlib.h. There is a workaround you can put in your .ycm_extra_conf.py file, which works by executing the C/C++ compiler and getting it to output the list of search paths - which includes the search path to find stdlib.h.

A better alternative to youcompleteme for C/C++ is to use cquery in combination with the LanguageClient-neovim. It will also find in c header files when used in a nix-shell if you install cquery from nixpkgs as it uses a custom shell wrapper

Python 3 support for vim

If you have defined your vim configuration in a `./my_vim.nix` file you can install vim with the python 3 support instead of python2 by overriding the python version like the following:

(pkgs.callPackage ./my_vim.nix {                                                                                                                                                          
      vim_configurable = vim_configurable.override { python = python3; };                                                                                                                     
})

gvim and gview

gvim and gview may be installed using the vimHugeX attribute name (package name vim_configurable).

$ nix-env -iA nixos.vimHugeX

System wide vim/nvim configuration

If you want a system wide "baseline" configuration for vim/nvim here are two examples: The vim example has python3 support as mentioned above.

{ pkgs, ... }:
{
  environment.variables = { EDITOR = "vim"; };

  environment.systemPackages = with pkgs; [
    ((vim_configurable.override { python = python3; }).customize{
      name = "vim";
      vimrcConfig.packages.myplugins = with pkgs.vimPlugins; {
        start = [ vim-nix vim-lastplace ];
        opt = [];
      };
      vimrcConfig.customRC = ''
        " your custom vimrc
        set nocompatible
        set backspace=indent,eol,start
        " ...
      '';
    }
  )];
}
{ pkgs, ... }:
{
  environment.variables = { EDITOR = "vim"; };

  environment.systemPackages = with pkgs; [
    (neovim.override {
      vimAlias = true;
      configure = {
        packages.myPlugins = with pkgs.vimPlugins; {
          start = [ vim-lastplace vim-nix ]; 
          opt = [];
        };
        customRC = ''
          " your custom vimrc
          set nocompatible
          set backspace=indent,eol,start
          " ...
        '';
      };
    }
  )];
}

import these in your configuration.nix and

{    
  imports =    
    [
      ./vim.nix
    ];
  # ...
}