Debugging Vim setup

While Vim’s core is very stable, problems can come about when extending the editor with plugins, particularly if there are a high number of them or if they’re buggy or not very well written. While Vim offers a number of ways to keep scripts’ behaviours isolated from one another, it may happen that you find Vim behaving in an unexpected way that you can’t quite pin down. There are a few very good approaches to figuring this out.

List your scripts

First of all, it helps to get a handle on what exactly you’ve got loaded during your Vim sessions. You can do this with the :scriptnames command:

:scriptnames
1: /usr/share/vim/vimrc
2: /usr/share/vim/vim73/debian.vim
3: ~/.vimrc
4: ~/.dotfiles/vim/autoload/pathogen.vim
...

This list appears in the order in which the files were loaded, which might give you a starting point for figuring out where the problem lies.

Update your plugins

Check the documentation, release logs, known problems, and in particular the website of your chosen plugins to see if there are any recent updates to them. If they’re hosted on GitHub, pull down the most recent versions.

Start with no plugins

You can start Vim with no plugins, in a pristine state that doesn’t source any vimrc files from your system or home directories, to figure out if the behaviour you’re observing still occurs with no plugins at all installed. This is done by calling Vim with the -u and -U options, which normally specify the path to a custom location for vimrc and gvimrc files respectively, with the special parameter of NONE:

$ vim -u NONE -U NONE

Vim will open and you’ll see the usual blue tildes for opening a line and Vim’s opening splash screen, having completely ignored your laborious setup.

This done, you can source plugins individually until you notice the problem starts happening, by a process of elimination:

:so plugin/fugitive.vim
:so plugin/unimpaired.vim
:so plugin/badplugin.vim

Profile startup time

If Vim was compiled with the +startuptime feature, you can also pass the --startuptime flag to it with a filename argument, and it will save a verbose log of its startup procedure to that file for you to inspect:

$ vim +q --startuptime startuptime.txt
$ vim startuptime.txt

There’s way more information in here than you’re ever likely to need, but in the case of a buggy setup or unacceptably slow startup time, it’s very useful for diagnosing the bottleneck in your setup.

Managing Vim plugins

While Vim’s built-in feature set is pretty vast and its tools can be adapted to pretty much any editing task, there’s still considerable value in using plugins to add functionality to the editor. Plugins range from simple functions or changes to the editing model, to complex behaviors that can make Vim compare in functionality to a full-blown IDE.

Selecting plugins

With the huge ecosystem of Vim plugins available and with experienced Vim users sharing their configurations and plugin setups proudly, it’s pretty easy to get excited and install umpteen plugins that you end up rarely if ever using. This is a bad idea for three main reasons:

  • Too many plugins, particularly low-quality ones, increases the loading time and the resource footprint of Vim.
  • Plugins often by design or accident break standard Vim functionality, meaning that when something goes wrong it’s irritating to diagnose which of your plugins caused it.
  • If you use many different machines, using a lot of plugins is burdensome if you have to keep them up to date, especially if the most recent version of Vim is not available to you on a particular machine.

Worse, some plugins, such as Cream, completely change the way Vim fundamentally works, which means if you install them early on in an attempt to get started with the editor you end up becoming reliant on the plugin for the most basic of editing tasks. It’s much better to actually learn Vim thoroughly first with a very minimal configuration, which will give you a much better idea of the feature set already available to you, and hence whether there’s any need to augment it. The general idea is that plugins should supplement Vim functionality, not replace it.

With this done, selecting plugins should be made based on two criteria: firstly, is it well-written and compatible, and secondly, do I actually need this functionality — that is, does it have some killer feature that makes my day much, much easier. If I can’t come up with a convincing use case for adding a plugin that would actually come up for me, then I don’t add it. Similarly, I don’t add anything that requires a lot of miscellaneous system dependencies or independent build procedures, which is why I don’t like the Command+T plugin much.

For example, at the moment I’m using the following plugins by Tim Pope:

  • Surround (supported by Repeat) which allows me to rapidly add, change, and delete delimiters of pretty much any kind around arbitrary text. Once you learn how to use this, it feels so natural that you wonder why it’s not in Vim by default.
  • Fugitive, a terrific plugin that brings a lot of Git functionality into Vim. The functions I most use in here are :Gblame to see where a block of code came from, and :Gdiff to add patches to and from the Git index for more meaningful commits.
  • Unimpaired, a set of matched mappings beginning with the square bracket keys. Most of them are at least moderately useful, but the killer feature for me here is the ability to escape and unescape text for XML, URLs, or C, which is really irritating to do by hand.

Managing plugins

If you plan to install extra plugins, I can’t recommend Pathogen enough. That’s also by Tim Pope. It allows you to keep plugins in their own directories in .vim/bundle, rather than interspersing them through directories like autoload and plugin. This makes keeping plugins updated much less laborious. Here’s how you can install it:

$ mkdir -p ~/.vim/bundle
$ cd ~/.vim
$ git clone git://github.com/tpope/vim-pathogen.git bundle/pathogen
$ mkdir autoload
$ cd autoload
$ ln -s ../bundle/pathogen/autoload/pathogen.vim

Then add the following into your .vimrc, after set nocompatible but before any filetype plugin settings:

silent! call pathogen#infect()

Now Pathogen should load for you any plugin you place in its own directory in .vim/bundle as if it had been added to the usual plugin and other directories. For example, to install Fugitive, you could run:

$ cd .vim/bundle
$ git clone git://github.com/tpope/vim-fugitive.git fugitive

Plugins as Git submodules

For a really high-tech Vim setup, consider managing your plugins as submodules of your dotfiles repository. Drew Neil explains this system very well in one of his Vimcasts.