The Warm Embrace of Vim, Part 2
When Vim starts up it goes through what are called runtime files. These are the files responsible for details like basic configuration settings, key mappings, syntax settings, color schemes, and plugins. The frosting on your Vim cake. On a *NIX based operating system, the default folder for these files will be your
$HOME/.vim folder. On a Windows computer, the default folder is
$HOME/vimfiles. There also exists the important vimrc file (.vimrc for *NIX, _vimrc for Windows), which by default, should exist in the $HOME directory.
Your vimrc file is where most of your basic initialization commands will go. Before Vim shows you anything, it goes through this file first for the settings it will use during each session. I’ll go over some of the ones I find to be the most important. How did I figure out what was the most important? Well besides the obvious and painful trial and error method, I bootstrapped my vimrc by finding other better Vim users (Steve Losh, Tim Pope, and Luca Pette are some strong examples), and parsed and compared their vimrc’s for settings that seemed to be common to all of them. This is a fine way for getting started but eventually I got a pretty good handle on what those settings meant to me and that’s what I aim to help you with here. I also have to point out the Vim documentation, which is borderline magnificent. If you need a deeper explanation on anything, your goto command is going to be
All of these settings can be directly cut and paste into your vimrc file. For the most part, order doesn’t matter except for a few which I’ll point out.
This is an important and special one. Setting
nocompatible tells Vim to act more like Vim and less like Vi, which is an ancestral version of our beloved editor. This one should be toward the top because it affects other settings that are Vim specific.
Because I use MacVim, setting Vim up for 8 bit unicode is a given and according to the Vim docs, “avoids unnecessary conversion overhead”.
Modelines are small bits of initialization code you put at the top or bottom of a file to make Vim behave slightly differently for that file. There’s some belief in the Vim community that this is exploitable though and since I don’t ever use this functionality, I’ve turned it off. Better safe than sorry.
set scrolloff=3 set wrap set linebreak set backspace=indent,eol,start set autoindent
Some simple settings that make Vim play a little nicer with my sense of what a editor should be like. For some continuity,
scrolloff is the number of lines always visible above and below the cursor as you move about the file.
linebreak tell Vim to wrap text and to do it only at word boundaries. The
backspace line is a must have. Without it, Vim annoyingly doesn’t backspace over indents, line breaks, and the start of inserts. You can also put
setbackspace=2 and get the same functionality but I like the more explicit phrasing seen here. Setting
autoindenttells Vim to maintain indenture when you start a new line.
set autoread set autowrite
autoread means Vim automatically reads in any externally updated files. Setting
autowritemeans whenever a buffer is switched or closed, save the changes to the disk. We haven’t talked about buffers but they’re basically “in-memory” representations of your file that you do work on before you save the changes back to the disk.
set ruler set number set mouse=a set wildmenu set wildignore=*~,.git,tmp,*.log set wildmode=list:longest,full
ruler gives us our cursor position in the form of “line, col” down in your statusline. You can customize this a bit and in fact, you can customize the whole statusline but it’s a little out of the scope of this tutorial and highly personal, but I implore you to learn more about it with the command
:h statusline inside Vim. You can put a lot of good info down there.
Another must have setting,
number gives us the very useful row numbers. There’s an alternative to this setting called
relativenumber which gives us the line number relative to our current position. This helps with movements like
10j (jump 10 lines down from the current position) but as far as I know, Vim only allows for one row number setting and I find the ever shifting numbers distracting, so I don’t use this one.
mouse=a forces non-gui versions of Vim to allow for mouse usage. The other side of this equation is the terminal though, as this doesn’t work in all of them.
wild settings give us tab completion functionality down on the command line. I set it up to ignore certain files and act more like bash completion. It’s called
tabacts as your wild character.
set shiftwidth=2 set shiftround set expandtab set tabstop=2 set softtabstop=2
The lines above are related to indentation and tabs. Ruby standard is indenture of two spaces per logical level without using tabs, so those settings may vary depending on your needs. If you’re wondering what the difference is between
softtabstop, I initially did too. My understanding is that if you’re trying to backspace over a tab you created while in Insert mode, if
softtabstop is not set, you’d have to hit backspace twice to delete over it since we have
expandtab turned on. Setting
softtabstop to 2 means backspace deletes two spaces. If that’s still confusing check out this excellent stackoverflow explanation.
set guioptions-=A "Disallows putting highlighted text into copy register set guioptions-=T "Disallows gui toolbar set guioptions-=m "Disallows gui menubar set guioptions-=r "Disallows right handed scrollbar set guioptions-=R set guioptions-=l "Disallows left handed scrollbar set guioptions-=L
These are various gui configurations that will probably be personal to me. You might notice the minus sign next to the equal sign. Depending on what version of Vim you’re on, certain settings will be defaulted to; the “-” is essentially telling Vim to subtract that option out if it’s there for whatever reason.
Some of personally useful mappings:
let mapleader = ","
A lot of hotkeyed commands use a mapping leader to initiate the command. For instance, I have a plugin called NERDtree that displays the tree structure of my current directory when I hit
,n to me. Even though I don’t foresee ever changing my mapleader, it is good practice to assign it to a variable. Using a comma as the leader is common in the Vim community and it made sense to me too, but that doesn’t mean you have to use it. Feel free to experiment.
imap hh =>
This one is Ruby specific, but hitting the equal sign and then the greater than sign over and over again is a pain in the butt. With this, I can double tap “h” to get a hash rocket. Disclaimer: Ruby 1.9 has made the colon syntax a very attractive alternative to the hash rocket (although I still like the hash rocket.) I think this illustrates just how low-level you can make these shortcuts though, so I’ve included it in this post.
A note on nomenclature when assigning mappings. Vim let’s you assign specific mappings to specific modes. When I used
imap hh, I told Vim to only use this mapping in Insert mode. Here are the mappings and modes useful to you right now. As always with Vim, there are deeper depths to what I’m showing you. If you want to check them out,
:h map is where you can start.
imap→ insert mode
nmap→ normal mode
vmap→ visual mode
map→ all modes
Another bit of subtlety you might see in your Vim adventures is the wording
noremap. By default in Vim,
remap is turned on. This means that if you were to take two keys that already have a meaning and try to assign one to the other, their meanings switch. That’s confusing so here’s an example,
map k j would turn
k into our scroll down command. Cool, that’s what we want BUT it would also reassign
j as our scroll up command. Their meanings switched. Generally, I don’t want that so
noremap ensures it doesn’t happen. As a rule of thumb, if something I’m assigning has a meaning to Vim, I use
noremap. I don’t want it to stick around in another form waiting for me to slip up and accidentally use it.
noremap <Ctrl-h> <C-w>h noremap <C-j> <C-w>j noremap <C-k> <C-w>k noremap <C-l> <C-w>l
Switching from window to window takes too many keystrokes in vanilla Vim. This makes it a bit easier for you.
Ctrl can be shortened to just
C. And my last favorite because I’m constantly tweaking my vimrc:
nmap <silent> <leader>ev :e $MYVIMRC<CR>
There’s a lot happening in this one so let’s break it down.
nmap→ normal mode mapping
<silent>→ I'm about to issue a command to the command-line but I don't necessarily care to see it there. This keeps it from showing up.
<leader>ev→ This is our hotkey, translating to
:e $MYVIMRC→ This the command we are issuing to Vim, edit our vimrc file, whose path is stored inside an environment variable called $MYVIMRC.
<CR>→ Carriage return, aka
Enter. Issues the command.
Basically, this allows me to edit my vimrc on the fly, whenever I feel a tweak is necessary. This is a great example of what makes Vim such a powerful tool. I I can hotkey a semi-complex set of commands to a couple keystrokes.
The plugins I’m about to describe to you make my life easier. I’ve heard some hardcore Vimmers say that Vim is beautiful the way it is. That they don’t need plugins to work effectively. A minimalistic Vim is a fast Vim, etc etc. This is wrong. Vim was built with extensibility in mind and not the exact needs of future languages. Besides, Vim stands for Vi Improved. If you’re using Vim, you’re already acknowledging the fact that programmers can’t predict the needs of future programmers. That improvements can always be made. So get some plugins. Nowadays, thanks to Tim Pope’s wonderful Pathogen plugin, there is almost no overhead to getting Vim running with them anyway.
This is a special one and should be the first you install. In the past, you’d have to separate out the component parts of each plugin into certain folders. Obviously this was a hassle. Pathogen allows you to maintain the plugin’s original file structure and retain its functionality. This comes in handy for quickly downloading and testing a plugin and keeps your vim folder clean, isolating each plugin in its own folder. To install:
cd ~/.vim mkdir autoload curl -so ~/.vim/autoload/pathogen.vim https://raw.github.com/tpope/vim-pathogen/HEAD/autoload/pathogen.vim
After this is installed, you need to create a folder called bundle in your vim folder (
mkdir bundle). This is where the rest of your plugins will go. There are a few different sources you can get the plugins from, but I’m partial to github because you can find all of the plugins I’m about to describe there, keeping things simple for me. One thing I highly recommend doing but is slightly more advanced is setting every plugin up as a submodule. This allows for quick updates and leaves the connection to the original source of the plugin intact. That’s a little out of the scope of this tutorial but there is a great one dedicated to it here.
The final thing you need to do is paste this into your vimrc at the very top:
call pathogen#infect() syntax on filetype plugin indent on
This plugin allows you to quickly find files based on a few letters from the file’s path or filename. As you type more letters, the choices get narrower and narrower. An awesome tool. This requires Vim to support Ruby, so ensure whatever version you’re using does by typing out
vim --version. If you’re using MacVim, you’re already good to go.
Version control on an atomic level. This plugin takes advantage of Vim’s undo history, allowing you to rollback a file to an arbitrary point in the file’s past. I use this a lot. Put this into your vimrc to hotkey:
nmap <silent> <leader>u :GundoToggle<CR>
Command-t is great for finding files but sometimes I want to see the whole file structure. This gives me a file tree that I can manipulate: I can open and close branches and files, see hidden files, change the current working directory, and bookmark files for quickloading.
nmap <silent> <leader>n :NERDTreeToggle %:p:h<CR>
A commenting tool that is able to handle commenting syntax for many different filetypes. Want to comment out a line without having to think about what the correct syntax is?
<leader>c<space> takes care of that for me. This acts as a toggle, so uncommenting is the same command. Easy peasy. There are some more fine grain commenting controls but this gets me through almost everything.
Another amazing plugin by Tim Pope is activated when you enter the root directory of a Rails application, adding a whole bunch of useful scripts and commands. The plugin remaps
gf (normally “goto file”) in a pretty incredible way. Let’s say we have a line in our model like
has_many :comments. Putting the cursor over a letter in
comments and hitting
gf brings us to the Comment model. Quite awesome.
Not an exciting plugin but ever dutiful. Install this for better all around Ruby experience, including indentation support, support for certain movements that require understanding of Ruby syntax (try
[mat the beginning or end of a method block), and completion support.
The Vim community is pretty robust and there’s a lot of people out there putting out great information. Here’s some places to start:
Derek Wyatt’s Vim Tutorials These videos helped me with my first steps into Vim and are a source of solid fundamentals.
Vimcasts For the folks who have the more basic stuff down and want to step up their Vim game, the screencasts here are worth a watch. The Fugitive plugin videos are top notch.
Vim Tips Wiki A great source of useful tips and tricks. As I get more advanced, I find myself learning things here that I would have never thought of on my own.
Vim’s a great editor. I’ve tried others that are built with a language in mind and I always end up coming back to Vim for its speed, simplicity, and customizability. When I’m in the zone, I want my world to be the text in front of me and not the distractions that come in the form of buttons and cpu expensive functionalities. I don’t want to dip into an IDE war because your choice in editor is just that, your choice, but if you’ve made it this far in the post, then you’re at least interested in Vim. So give it a solid shot and figure out if it’s right for you.
If you have an tips, tricks, plugins, or just general thoughts/questions on Vim, feel free to post them! Thanks for reading.