Kevin's Vim Tips and Tricks

Overview

This document is a set of tips and tools that I've found to be useful over the years of using vim. This is by no means a "tutorial" - see :help tutor for that. I also don't claim to be a vim expert. These are just some of the most useful things I've discovered so far with vim.

My vimrc (html version).

Remapping the escape key

The first thing you need to do to make using Vim easy is to remap the Caps Lock key to be a Ctrl key. This serves two purpose:

You can remap the Caps Lock key in one of several ways:

Windows and Buffers

Now that you can quickly navigate between insert and command mode, you should learn how to quickly navigate between files and buffers.

The Basics

The first tip is pretty basic but essential: window creation and manipulation is done with the CTRL-w prefix. The commands you should know by heart are:

CTRL-w n Creates a new window above the current window
CTRL-w j Moves the cursor to the window below the current one
CTRL-w k Moves the cursor to the window above the current one
CTRL-w s Splits the current window - creates a new window editing the same file as the current window
CTRL-w o Make the current window the only window. Closes all other windows.

There are many other commands, but these are the basics for using windows.

Some useful keyboard maps

A lot of times, I'll have three or four windows open in vim. This presents a couple problems. First, each of the windows is small - you can't see that much information. Second, if I want to go from the bottom window to the top window, I have to hit CTRL-w k three or four times. To solve these two problems at once, I have two additional keyboard maps in my .vimrc file:

set winminheight=0      " Allow windows to get fully squashed

"
" Switch between windows, maximizing the current window
"
nnoremap <C-J> <C-W>j<C-W>_
nnoremap <C-K> <C-W>k<C-W>_

With these settings, if you type CTRL-j, you will move to the window below and maximize it in a single keystroke. Conversely, CTRL-k will move up a window and maximize it. This makes it much more efficient to switch between windows when you have many of them open.

Note the winminheight=0 setting. This allows the inactive windows to squish down to one line.

Bufexplorer

One of the most useful extensions for vim is Bufexplorer. Download the zip file and extract it inside your ~/.vim/ directory (if you don't have one yet, create one - we'll be putting other stuff in there). Note that the later versions only work for vim 7.0 and above. If you are using an earlier version, install version 7.0.11 from the site.

Once you've installed it, rerun vim. Open a few different files using :n, and then type \be. This will open a list of all the buffers (files) you have edited. There are lots of options on how to sort and display the files, but personally I prefer the defaults.

Once you get the hang of bufexplorer, you won't need to close vim. Just leave it open, and it will accumulate buffers. You can use bufexplorer to re-open a file you had open earlier with ease.

File navigation

Speaking of opening multiple files, there is a file/directory browser built in to vim. All you have to type is :n .<Enter> and a listing of the current directory will be displayed. Hit Enter on a directory to change to that directory and Enter on a file to edit that file. Recent version of Vim even have the ability to browse and edit files across the network!

Tags

Tags are one of the best ways to navigate around a large set of files in vim. I'm sure you are familiar with the concept of tags, but there are a few tweeks you can make in vim to make them even more useful.

Find the tags wherever you are

If you have multiple tag files (across different projects), or your current working directory changes, it is useful to have vim search recursively upwards for the tags file. To enable this, add to your .vimrc:

set tags=tags;/

I used to like for vim to automatically change directory for the current open file, but I now employ a few macros in place of this. Having a stable working directory makes plugins happier and allows for things like :make to work better.

" Edit a file in the same directory as the current buffer.
" This leaves the prompt open, allowing Tab expansion or manual completion.
nnoremap <leader>e :e <C-R>=expand("%:p:h") . "/" <CR>

" Enter directory listing for the directory of the current buffer
nnoremap <leader>. :e %:p:h<CR>

" Create a new window with directory listing of current buffer
nnoremap <leader>wn :new %:p:h<CR>

" Change global directory to the current directory of the current buffer
nnoremap <leader>cd :cd %:p:h<CR>

Jumping to tags

There are several ways to jump to a tag, the most basic is one of:

but the problem with these two is that they always pick the first match. Many times there will be multiple matches and you then have to use :tn to find the right one. A better way (IMO) is using the :tj[ump] command. If there is more than one result, it presents a list of matches, otherwise it jumps straight to the result. Ways to invoke this are:

By the way, :tj supports completion using Tab and CTRL-D. If you like completion, you may want to turn on wildmenu in your .vimrc.

:tj also support regular expressions. You can enter :tj /\.spec$<Enter> to list all the spec files, for instance (but see the next topic for how to enable spec files to be indexed by ctags).

Searching for more than just source code files

Once you get used to using tags to jump between files, it can be disappointing to try to go to a file that wasn't indexed by ctags. With exuberant ctags, there is a way to tell it to index filenames in addition to tags within those files. You can also tell it to record the filenames of files that it otherwise wouldn't index (such as xml or spec files).

To enable this extra indexing, invoke ctags as follows:

ctags --extra=+f \
      --langdef=file \
      --langmap='file:.ext1.ext2.ext3' \
      -R 

Put your extensions in place of ext1/2/3 and add as many extensions as you want. (It's helpful to put this in a shell script, btw). This way, you can jump to a file the same as a method or variable in a file, for example: :tj build.xml

The Taglist plugin

Whether you use tag files or not, another plugin you should try is taglist. This allows you to put a list of tags for the current file on the left (or right) side of the window. This makes it easy to find the function or declaration in a file quickly. Just download and unzip inside your .vim directory.

The settings I've found useful to put in my .vimrc are:

nnoremap <silent> <F8> :TlistToggle<CR>
let Tlist_Exit_OnlyWindow = 1     " exit if taglist is last window open
let Tlist_Show_One_File = 1       " Only show tags for current buffer
let Tlist_Enable_Fold_Column = 0  " no fold column (only showing one file)
let tlist_sql_settings = 'sql;P:package;t:table'
let tlist_ant_settings = 'ant;p:Project;r:Property;t:Target'

The first line creates a mapping so that pressing <F8> toggles the taglist open and closed.

The Tlist_Exit_OnlyWindow closes vim if when you close the last window besides the taglist.

The Tlist_Show_One_File is a matter of preference. This instructs taglist to only show a list of tags for the current window. Without this set, taglist accumulates tags as you open files.

The last two lines bear special mention. They instruct taglist to show information about SQL and Ant (xml) files. In order for the ant settings to work, you have to tweek the ctags configuration which is the subject of the next section.

Adding new files for ctags to index

Exuberant Ctags is extensible. You can instruct it to search for certain regular expressions. To do this, you need to add entries to a .ctags file in your home directory. The details for this are beyond the scope of this document, but I will put the contents of my .ctags file as a starting example here. From there I recommend you look at the exuberant ctags documentation.

--langdef=ant
--langmap=ant:.xml
--regex-ant=/^[ \t]*<[ \t]*project.*name="([^<"&]+)"/\1/p,project/i
--regex-ant=/^[ \t]*<[ \t]*target.*name="([^<"&]+)"/\1/t,target/i
--regex-ant=/^[ \t]*<[ \t]*property.*name="([^<"&]+)"/\1/r,property/i

Completion

There's only one command to know here: CTRL-n. If you use it while typing a function or variable name, it will provide a list of possible completions. While it's not as smart as a modern Java IDE, it works across all languages. This works even better in Vim 7.0. If you leave your editor open for long periods of time it will learn more things to complete as you open new files.

Visual Mode

If you're using Vim then you probably already know about visual mode. Type :help visual-mode if you don't already, because it's one of the best features of vim. I only want to point out a couple commands here that I've found useful:

CTRL-v jjjjj[...] I If you select a rectangular block and then type I, you can then insert text in front of the block on each line.
CTRL-v jjjjj[....] A If you select a rectangular block and then type A, you can then append text at the end of the block on each line.
CTRL-v $ jjjjj[....] A If you put a $ at the beginning vim will "remember" you've selected to the end of the line. This will allow you to append text at the end of each line even if the lines are of varying length.

Searching

Vim offers a way to highlight the results of the current search: set hlsearch. The problem is that it stays on. You can turn it off, but you have to type :nohlsearch (over and over and over...).

I find it much more convenient to be able to toggle it on and off as I feel like it. To do this, I put in my .vimrc:

set nohlsearch          " turn off highlight searches, but:
                        " Turn hlsearch off/on with CTRL-N
nnoremap <silent> <C-N> :se invhlsearch<CR>

You can then hit CTRL-n to toggle the highlight on/off.

My Preferences

These aren't tips, so much as a plug for some of my preferences.

Favorite color schemes

Favorite plugins



Last modified: Jul 02, 2013 11:13