So I promised I will explain my vim setup in this part of the series. And of
course, I will do this.
The requirements
The requirements are fairly easy here. I wanted to be able to use
YouCompleteMe with vim, so I need a vim with Python support enabled. So, I
absolutely need the configurable vim package from the NixOS package tree and I
clearly must override it. And when doing this step, I can remove all the stuff
from the vim package I do not need.
Another requirement was that I can replace vim with neovim. I've not done this
yet, but I guess it should be fairly easy.
Because not all vim plugins are in the NixOS packages, I need to be able to
build my own packages outside of the NixOS package tree and pack them into my
store as well.
And, because vim needs to know all these plugins, I must be able to override
the runtimepath
variable in the vim configuration, the vimrc. So, I need to
be able to compile the vimrc out of the package definition as well.
The setup
The directory setup here is fairly easy. I have my normal configuration folder
whereas I created a folder vim
inside the pkgs
folder:
config/nixos/
|
+– ./pkgs/
|
+– vim.nix
+– vim
|
+– override.nix
+– pkgPlugins.nix
+– plugins.nix
+– vimrc/
|
+– colorscheme.vim
+– filetypes.vim
+– ...
+– vimrc.nix
Let me elaborate what is located where here.
vim.nix
The top-level file for the vim packaging. This file is actually included in my
machine-specific configuration or in the pkgs/basePackages.nix
file, so my
vim is always installed on every system. The latter is the way I want to do
this, so I have the same vim on all systems.
This file returns a list.
vim/override.nix
This file simply contains the overridden vim package.
This file returns a package / derivation.
vim/pkgPlugins.nix
This file contains the already packaged plugins. I do not have to compile
them, as they are already in the NixOS package tree, which makes certain
things simple but others more complex, we will see why.
This file returns a list.
vim/plugins.nix
Self-packaged plugins. Period.
This file returns a list.
vim/vimrc.nix
This file uses all files in pkgs/vim/vimrc/*.vim
and compiles them into one
giant string and writes this one as vimrc
file to the store. Actually, there
is a pkgs/vim/vimrc/plugins.nix
file in the directory which compiles
pkgs/vim/vimrc/plugins/*.vim
files into a string and returns that string,
which simply gets included in the vimrc
. I did this for abstraction, so the
configuration for each file lives into the appropriate subdirectory.
The How
Lets start with the easy parts here first. To override vim, you don't really
have to do much things. What you have to do can be explained best with the
appropriate nix file:
Override vim
{ pkgs, lib, vimrc }:
let
vim = lib.overrideDerivation pkgs.vimconfigurable (o: {
aclSupport = false;
cscopeSupport = true;
darwinSupport = false;
fontsetSupport = true;
ftNixSupport = true;
gpmSupport = true;
hangulinputSupport = false;
luaSupport = true;
multibyteSupport = true;
mzschemeSupport = true;
netbeansSupport = false;
nlsSupport = false;
perlSupport = false;
pythonSupport = true;
rubySupport = true;
sniffSupport = false;
tclSupport = false;
ximSupport = false;
xsmpSupport = false;
xsmpinteractSupport = false;
postInstall = (o.postInstall or “”) + ''
ln -sf “${vimrc}” “$out/share/vim/vimrc”
'';
});
in vim
Of course, you have to make sure that this is the only occurance of vim in
your package setup. And if you install vim in a user environment, it will
override this as well, so be warned!
So I ripped out everything I don't need here, which is for example tcl
support. I don't even know what tcl
is, actually.
You also need to override the postInstall
hook to ensure you link the
vimrc
to the appropriate path. The vimrc
file must be passed to this
function, as you can see in the first line.
Packaged plugins
The second thing which is fairly easy is the file for the plugins which are
already in the NixOS package repository. What I do here is simple:
{ stdenv , pkgs }:
[
pkgs.vimPlugins.youcompleteme
# pkgs.vimPlugins.
# ...
]
And yes, it is that simple. I will not share my entire config files here, of
course. You don't need to know what kind of plugins I use in my vim setup!
More plugins!
Now comes the more difficult part. I actually copied these definitins from
aszlig:
{ stdenv
, pkgs
, lib
, writeTextFile
, writeText
, buildEnv
, fetchgit
, vim_configurable
}:
with stdenv;
let
# ... here were some things I did not need
mkVimPlugins = plugins: buildEnv {
name = “vim-plugins”;
paths = with lib; mapAttrsToList (const id) plugins;
ignoreCollisions = true;
postBuild = ''
find -L “$out” -mindepth 1 -maxdepth 1 -type f -delete
'';
};
pluginDeps = { };
plugins = mkVimPlugins (pluginDeps // {
vimvim-fugitive = fetchgit {
url = “https://github.com/tpope/vim-fugitive";
rev = “”;
sha256 = “”;
};
# ...
});
in [plugins]
As you can see, this file is a bit longer than the previous ones. I only
inserted the fugitive plugin for posting here, obviousely. So how does this
work? Each plugin gets fetched with git (for fetching from vimscripts or other
methods of fetching, look at aszligs repo,
this file, actually).
After it was fetched from git, it is inserted in a set which is afterwards fed
to the mkVimPlugins
function, which adds all the plugins to one package. All
plugin pathes are added to the package then. Why you need the
ignoreCollisions = true;
line... I'm not sure but I guess it ensures that
two plugins can have files with same names. I'm also not sure about the
postBuild
hook.
But that's how it is supposed to work. It returns a list of plugins, then.
Lets build a vimrc!
Yes, I actually compile my vimrc out of nix expressions. That's not that hard,
it is actually string concatenation, because I do write .vim
files.
{ stdenv, writeText, additionalRTP }:
let
generic = builtins.readFile ./vimrc/general.vim;
# ...
statusline = builtins.readFile ./vimrc/statusline.vim;
# ...
plugins = import ./vimrc/plugins.nix;
in
writeText “vimrc” ''
${generic}
set runtimepath+=${additionalRTP}
set runtimepath+=${additionalRTP}/after
set runtimepath+=${additionalRTP}/share/vim-plugins
${statusline}
${plugins}
''
That's really easy: I read the files which contain the vim configurations
(general configuration, statusline, etc) and put them all together.
What I add as well: The additional runtime path. This is actually required
because when installing vim packages which are not in the package tree of
NixOS by now, vim cannot find these. When adding the additional runtime path
here, I tell vim to look in these directories as well, ensuring that the
plugins can be found.
The last point is obviousely one point I have to clean up, because I guess
there should be a better way how to do this. As you might notice when
setting up your vim configuration on NixOS, there is also an plugin manager
for vim you can use from within NixOS/the nix packages. It gives you lazy
loading of vim plugins and all these nice things you want to have. I'm not
sure how this fits into the way how NixOS packages vim plugins, I guess I have
to dig around here a bit.
Anyhow, it works. On my testing machine, which is an rather old machine (not
that old, but also not the new shit, you know) vim starts up in about 1
second. This is obviousely way to much for a machine I want to use for
developing software, but for this machine it is okay.
Maybe this will get better after cleaning up the setup, I'm not sure.
In the next part of the series, I will explain my bash(rc) setup, which is
handled by nix, of course. Maybe I can also elaborate on my vim setup, if I
managed to clean up the mentioned parts.
tags: #linux #nixos