Getting More From Vim

If you're a Linux administrator, no matter what size your environment, it's quite likely that you use Vim. You probably use it as a config file editor, or for light programming tasks. If you're already familiar with the basics, have a look at some slick tips that'll have you using Vim for more than just ho-hum, everyday admin tasks. 

I use Vim for everything. I started out using it for simple config file edits, bash or Perl scripts, and trivial notes. I used to use Zend Studio for PHP programming, Quanta Plus, Bluefish, or Screem for HTML, OpenOffice.org for documentation, and tools like gedit for drafting email and longer, personal notes (like my personal "tips and hacks" log file). However, over the past couple of years, I've learned to configure Vim to use it for all of these tasks. To me, it makes more sense to try to use one editor for all of my editing tasks if possible (without writing code, of course).

Vim configuration

Vim allows for several configuration file options. If you have a .vimrc file in your home directory, it uses that. It can also take a user-specified configuration file at the command line using the -u flag. This is useful if Vim chokes on some new config option you're trying out, because you can use, for example, vim -u NONE to bypass your config file altogether. Finally, in the absence of either of these options, Vim uses a default, system-wide configuration file, generally /etc/vimrc.

Another handy way to configure Vim is to do it interactively and save your settings at the end of the session. For example, on my Fedora Core 2 laptop, a new user account (which uses the global Vim configuration by default) has the formatoptions option set to tcql. To see what yours is set to, type :set formatoptions?. All of the letters the command returns represent a different enabled format option. The t means to use line wrapping. If you wanted to use only the t option, you would type (in normal mode) :set formatoptions=t.

Typing :set textwidth? shows me that none is set, meaning an actual line break doesn't get entered unless you press Enter. This can be a bit deceiving, because Vim appears to wrap lines at the window border of your terminal. However, typing :set list shows the non-printable characters, including the line boundaries, which appear as dollar-sign characters. If you type a 200-character line and a carriage return in a 72-character wide window, the lines will seem to wrap, but :set list will show you that there's only a single end-of-line. To prove it another way, putting the cursor on the 200th character and hitting the "0" key in normal mode will bring you to what Vim sees as the beginning of the line, which will be character 1, whether that looks to you like it's the same line or not. To get the configuration right for human-readable text files, I generally use :set textwidth=72.

NOTE: Notice that typing :set followed by any option and a question mark shows you what the option is set to. To see all of the options and their current values, type :set all, without a question mark. Also, if you don't want to use a textwidth, but don't want Vim to break lines unless you tell it to, use the option :set nowrap.

Once you've set your options and have things the way you like them, you can type :mkvimrc, and Vim will save all of the options currently in effect to a .vimrc file in your home directory.

Acting differently depending on file type

In all likelihood, you don't edit only one type of file. You might have Perl, bash, Python, HTML, PHP, SQL, and C program files in addition to your normal array of configuration files. If you turn on filetype recognition in Vim, you can set up different options for each of these types of files. Here's a short section of my .vimrc file to use as an example:

filetype on
autocmd FileType html,mail set formatoptions=tq textwidth=72
autocms FileType perl set smartindent nowrap

As you can see, I've told Vim to turn on filetype detection. Once that's turned on, I set options common to HTML and mail files using a single autocommand. However, as your customization for each filetype grows, you may choose to source a separate file for different filetypes, like this:

autocmd FileType html source $HOME/.vimrc.html

This can make debugging easier and your main .vimrc file a bit cleaner to look at. It also ensures that misconfigurations in your HTML configuration don't make the editor unusable for text files, and vice versa.

Mapping shortcut keys

This is where a lot of the real fun starts. Most of the customizations I use are keyboard mappings configured to make repetitive tasks as easy as hitting a single key. Keys can be mapped to internal Vim commands, external shell commands, or even Vim functions you write yourself!

The examples I'll use to illustrate the mapping features all come from my own use of Vim. I use Vim to write my Sysadmin to Sysadmin articles every week. I write them in plain HTML, but there are some rules that we writers, along with the editors and formatting people, have agreed upon to make life easier for all three parties. One rule is that file names and commands that are typed in the middle of a sentence be enclosed with <code> tags. I use this feature a lot, and so I've created a key mapping that puts my tags in, and then places my cursor in between them:

imap <F12> <code> </code> <Esc>2F>a

What this says, from left to right, is that this mapping will be effective only in "insert" mode (hence "imap"; visual mode mappings use "vmap" ... you get the idea). Then I choose my target key affected by the mapping -- F12 in this case. What follows that are the literal keystrokes that F12 will replace. Since we're starting in insert mode, the two tags will be typed in, and then we'll enter Escape to enter command mode. At that point, entering 2F>a tells the editor to search backward for the second occurrence of ">" (2F>), and append (a). This also puts us back in insert mode. In fact, when you press F12 while you're in insert mode, you never know you left insert mode, which is nice.

Using shell commands from within Vim can often prove quite useful, even if it's a brute-force way to do something you don't know how to do otherwise. My example here does a word count. I check my word count often while I'm writing these articles, because at some point I know I have to start wrapping things up before I get too long-winded. I can't imagine there isn't a way to do this in Vim, but I haven't found it, so I do it this way:

map <F5> :!wc -w %; sleep 3 <Enter><Enter>

The above line configures things such that when you press F5 in normal (command) mode, it executes wc -w on the current file, then gives you three seconds to look at the output. It then presses the Enter key twice to get you back to your file. The important part to remember here is that you need to prepend the :! to the shell command! The colon says you're about to enter a command, and the exclamation point says that the command will not be a Vim or Ex command, but rather an external shell command.

In closing

The possibilities of key mapping are seemingly endless -- you could probably spend the rest of your weekends for the rest of the year just customizing Vim for all of the different tasks you do.

Scripting Vim, working on multiple files, using multiple buffers, and split window shortcuts are all left as exercises to the user. I highly recommend doing a search for "my .vimrc file" on Google, since many people post their own configuration details, which can be very handy. For those who really want to get a thorough grounding in all that Vim has to offer, I strongly recommend Steve Oualline's "Vi IMproved -- Vim". This is a fantastic book.

Finally, if you have a minute, please post your own killer .vimrc one-liner or even a Vim function here as a comment to this article. It'll give me and others something to bookmark for reference, and it's always fun to share hints and hacks with other Vim users!