November 15, 2011
The first time I used vi was in the mid-1990s while working on a project that used Aix servers. Coming from a predominately Mainframe background, the power of the Unix command line was new to me, and vi was exotic and exciting. I still have a spiral bound stenographers notebook filled with pages of notes on the often cryptic commands I was using and learning.
In the intervening fifteen years I have continued to use vi on and off, but I have never used it exclusively. There have been any number of other, graphical-based editors to play with, most recently TextMate on Mac OS X.
Last winter I read with great interest Jonathan Snook's piece on exploring Vim. He rationale for learning Vim was to satisfy the need to learn something new every day. That struck me as a good idea, and learning the modern version of vi, Vim, seemed like a worthy goal. At the very least it would provide many, many opportunities to learn something new everyday.
In the Snook article he linked to a set of screencasts by Derek Wyatt. After watching most of these I was determined to learn Vim.
I started by getting the O'Reilly book Learning the vi and Vim editors. Reading dense textbooks is a way to learn something new, but doing is where the real learning takes place. Using Homebrew I installed MacVim and started playing around.
Somewhere along the way I discovered the Janus set of plugins, which take alot of the pain of setup away. I happily used this configuration throughout much of the summer. After installing Mac OS X Lion (10.7) I started having problems with my Vim setup, and so I have started over and built a setup for me that works, and that I understand more intimately.
The rest of this posting outlines how I built Vim using Homebrew, describes some of the configurations I've made in my .vimrc file, how I'm using git and git submodules to version my setup so I can share it to all my computers, and the list of bundles that I am currently using to extend Vim's functionality.
While Mac OS X comes with a version of Vim, the compile options for that version did not support everything I wanted. You can view the options by opening a Vim session, and then issuing the :version command. Any option listed with a + is included, those with - signs are not included. The default Vim doesn't include ruby and it was giving me SegV errors whenever I tried to use it with a Ruby other than the default 1.8.x that Mac OS X comes with.
I resolved the Vim issues by using Homebrew to install MacVim, and by specifying that the Homebrew installed version override the system default version.
brew install macvim --override-system-vim
I was careful to run this command while using the Mac OS X default Ruby version. Compiling MacVim with a 1.9.x version of Ruby will fail as not all of MacVim's dependencies will work with 1.9.x.
Vim is highly configurable, and there are dozens of plugin bundles available to add or alter functionality. Using a ready made bundle set like Janus can save you time and effort. However, in the spirit of learning every day, I opted to create my own .vimrc file.
The excellent Steve Losh article Coming home to Vim was my guide during much of this process. I liberally copied chunks of his .vimrc file, and installed some of the bundles he uses.
Here is my entire .vimrc file.
I've noted in the comments at the beginning of the file the various sources I've used while building it. The VimCasts.org site is a goldmine of great information, complete with code sample for you to use in your .vimrc file.
It was through one screencast in particular that I was able to cleanly and easily setup a Git repository for my Vim configuration. This repository makes use of Git submodules for the installed bundles, many of which are already Git repositories.
In my case I created a new hidden directory in my home directory called .dotfiles. I then moved my .vimrc file and .vim directory to this new directory. Next I created symlinks in my home directory to point to the actual files in the .dotfile directory.
mkdir .dotfiles mv ~/.vimrc ~/.dotfiles/vimrc mv ~/.vim ~/.dotfiles/vim ln -s ~/.dotfiles/vimrc ~/.vimrc ln -s ~/.dotfiles/vim ~/.vim
Next I created a Git repository in the .dotfiles directory, added a README file, created a cooresponding Github repository, and mated my local repository to the remote on Github.
cd ~/.dotfiles git init mvim README.markdown git add . git commit -m "initial commit" git remote add origin email@example.com:zan5shin/dotfiles.git git push -u origin master
You can see the instructions I put inside my README on my dotfile repository on Github.
Once the repository has been pushed to Github it is now simple to use the same configuration on any machine, simply by cloning the repository and adding a couple of symlinks.
Based on advice from Steve Losh and the vimcasts.org screenscast, I am using the pathogen plugin to manage bundles for Vim. This plugin makes it simple to add or remove plugins to you Vim configuration. Since most plugins are already Git repositories themselves, you simply clone the appropriate repository inside your ./vim/bundle directory and you are good to go.
However, since your .vim directory is contained inside a Git repository you should use Git submodules to manage plugins which are themselves Git repositories.
From the root of your Vim configuration repository use git submodule add to clone the plugin repository and add it to the submodule list. For example, here are the steps to add vim-fugitive, a plugin for working with Git.
cd ~/.dotfiles git submodule add https://github.com/tpope/vim-fugitive.git vim/bundle/fugitive git commit -m "installed vim-fugitive" git push
The screencast on synchronizing with git and pathogen explains these steps beautifully.
Once you have added one or more bundles, committed those changes to you local repository, and push that repository to Github, you are ready to share this new configuration with any other clones you may have created.
The initial clone on a second (or third, or n-th machine) looks like this:
cd ~ git clone http://github.com/username/dotfiles.git .dotfiles ln -s ~/.dotfiles/vimrc ~/.vimrc ln -s ~/.dotfiles/vim ~/.vim cd ~/.dotfiles git submodule init git submodule update
The last two commands above are necessary to initialize and update the submodule repositories. If you only have one bundle installed this seems like extra work, but once you have several bundles installed, the submodule system pays off.
Subsequent updates of a specific bundle goes like this:
cd ~/.dotfiles/vim/bundle/fugitive git pull origin master
You can also use the foreach command to update all bundles at once. This is run from the root of your repository, where the .gitmodules file is located.
git submodule foreach git pull origin master
One caveat to be aware of, as you update plugins via Git you may get messages about the repository tree being dirty. In order to avoid that, following the link at the end of the screencast posting, I added ignore = dirty to each submodule entry in the .gitmodules file as I added plugins.
Here is my .gitmodules file:
[submodule "vim/bundle/fugitive"] path = vim/bundle/fugitive url = http://github.com/tpope/vim-fugitive.git ignore = dirty [submodule "vim/bundle/solarized"] path = vim/bundle/solarized url = git://github.com/altercation/vim-colors-solarized.git ignore = dirty [submodule "vim/bundle/gundo"] path = vim/bundle/gundo url = https://github.com/sjl/gundo.vim.git ignore = dirty [submodule "vim/bundle/nerdtree"] path = vim/bundle/nerdtree url = https://github.com/scrooloose/nerdtree.git ignore = dirty [submodule "vim/bundle/nerdcommenter"] path = vim/bundle/nerdcommenter url = https://github.com/scrooloose/nerdcommenter.git ignore = dirty [submodule "vim/bundle/command-t"] path = vim/bundle/command-t url = git://git.wincent.com/command-t.git ignore = dirty [submodule "vim/bundle/syntastic"] path = vim/bundle/syntastic url = https://github.com/scrooloose/syntastic.git ignore = dirty
There are many bundles to choose from, and as a rank beginner at Vim, I've only scratched the surface. Still, here are the bundles that I've incorporated into my setup, along with a brief description of each.