👉 Latest post:
"Why .every() on an empty list is true"
By Vincent Driessen
on Tuesday, September 14, 2010

A few weeks ago, I felt inspired by articles from Jeff Kreeftmeijer and Armin Ronacher. I took some time to configure and fine-tune my Vim environment. A lot of new stuff made it into my .vimrc file and my .vim directory. This blog post is a summary describing what I’ve added and how I use it in my daily work.

Before doing anything else, make sure you have the following line in your .vimrc file:

" This must be first, because it changes other options as side effect
set nocompatible

Step 0: make the customization process easier

Before starting configuring, it’s useful to install pathogen. Plugins in Vim are files that you drop in subdirectories of your .vim/ directory. Many plugins exist of only a single file that should be dropped in .vim/plugin, but some exist of multiple files. For example, they come with documentation, or ship syntax files. In those cases, files need to be dropped into .vim/doc and .vim/syntax. This makes it difficult to remove the plugin afterwards. After installing pathogen, you can simply unzip a plugin distribution into .vim/bundle/myplugin, under which the required subdirectories are created. Removing the plugin, then, is as simple as removing the myplugin directory.

So, download pathogen.vim, move it into the .vim/autoload directory (create it if necessary) and add the following lines to your .vimrc, to activate it:

" Use pathogen to easily modify the runtime path to include all
" plugins under the ~/.vim/bundle directory
call pathogen#helptags()
call pathogen#runtime_append_all_bundles()

Next, I’ve remapped the leader key to , (comma) instead of the default \ (backslash), just because I like it better. Since in Vim’s default configuration, almost every key is already mapped to a command, there needs to be some sort of standard “free” key where you can place custom mappings under. This is called the “mapleader”, and can be defined like this:

" change the mapleader from \ to ,
let mapleader=","

Once that is done, this is a little tweak that is a time-saver while you’re building up your .vimrc. Here, we start using the leader key:

" Quickly edit/reload the vimrc file
nmap <silent> <leader>ev :e $MYVIMRC<CR>
nmap <silent> <leader>sv :so $MYVIMRC<CR>

This effectively maps the ,ev and ,sv keys to edit/reload .vimrc. (I got this from Derek Wyatt’s .vimrc file.)

Change Vim behaviour

One particularly useful setting is hidden. Its name isn’t too descriptive, though. It hides buffers instead of closing them. This means that you can have unwritten changes to a file and open a new file using :e, without being forced to write or undo your changes first. Also, undo buffers and marks are preserved while the buffer is open. This is an absolute must-have.

set hidden

These are some of the most basic settings that you probably want to enable, too:

set nowrap        " don't wrap lines
set tabstop=4     " a tab is four spaces
set backspace=indent,eol,start
                    " allow backspacing over everything in insert mode
set autoindent    " always set autoindenting on
set copyindent    " copy the previous indentation on autoindenting
set number        " always show line numbers
set shiftwidth=4  " number of spaces to use for autoindenting
set shiftround    " use multiple of shiftwidth when indenting with '<' and '>'
set showmatch     " set show matching parenthesis
set ignorecase    " ignore case when searching
set smartcase     " ignore case if search pattern is all lowercase,
                    "    case-sensitive otherwise
set smarttab      " insert tabs on the start of a line according to
                    "    shiftwidth, not tabstop
set hlsearch      " highlight search terms
set incsearch     " show search matches as you type

There is a lot more goodness in my .vimrc file, which is put in there with a lot of love. I’ve commented most of it, too. Feel free to poke around in it.

Also, I like Vim to have a large undo buffer, a large history of commands, ignore some file extensions when completing names by pressing Tab, and be silent about invalid cursor moves and other errors.

set history=1000         " remember more commands and search history
set undolevels=1000      " use many muchos levels of undo
set wildignore=*.swp,*.bak,*.pyc,*.class
set title                " change the terminal's title
set visualbell           " don't beep
set noerrorbells         " don't beep

I don't like Vim to ever write a backup file. I prefer more modern ways of protecting against data loss.

set nobackup
set noswapfile

There have been some passionate responses about this in comments, so a warning may be appropriate here. If you care about recovering after a Vim or terminal emulator crash, or you often load huge files into memory, do not disable the swapfile. I personally save/commit so often that the swap file adds nothing. Sometimes I conciously kill a terminal forcefully, and I only find the swap file recovery process annoying.

Use file type plugins

Vim can detect file types (by their extension, or by peeking inside the file). This enabled Vim to load plugins, settings or key mappings that are only useful in the context of specific file types. For example, a Python syntax checker plugin only makes sense in a Python file. Finally, indenting intelligence is enabled based on the syntax rules for the file type.

filetype plugin indent on

To set some file type specific settings, you can now use the following:

autocmd filetype python set expandtab

To remain compatible with older versions of Vim that do not have the autocmd functions, always wrap those functions inside a block like this:

if has('autocmd')
    ...
endif

Enable syntax highlighting

Somewhat related to the file type plugins is the syntax highlighting of different types of source files. Vim uses syntax definitions to highlight source code. Syntax definitions simply declare where a function name starts, which pieces are commented out and what are keywords. To color them, Vim uses colorschemes. You can load custom color schemes by placing them in .vim/colors, then load them using the colorscheme command. You have to try what you like most. I like mustang a lot.

if &t_Co >= 256 || has("gui_running")
    colorscheme mustang
endif

if &t_Co > 2 || has("gui_running")
    " switch syntax highlighting on, when the terminal has colors
    syntax on
endif

In this case, mustang is only loaded if the terminal emulator Vim runs in supports at least 256 colors (or if you use the GUI version of Vim).

Hint: If you’re using a terminal emulator that can show 256 colors, try setting TERM=xterm-256color in your terminal configuration or in your shell’s .rc file.

Change editing behaviour

When you write a lot of code, you probably want to obey certain style rules. In some programming languages (like Python), whitespace is important, so you may not just swap tabs for spaces and even the number of spaces is important.

Vim can highlight whitespaces for you in a convenient way:

set list
set listchars=tab:>.,trail:.,extends:#,nbsp:.

This line will make Vim set out tab characters, trailing whitespace and invisible spaces visually, and additionally use the # sign at the end of lines to mark lines that extend off-screen. For more info, see :h listchars.

In some files, like HTML and XML files, tabs are fine and showing them is really annoying, you can disable them easily using an autocmd declaration:

autocmd filetype html,xml set listchars-=tab:>.

One caveat when setting listchars: if nothing happens, you have probably not enabled list, so try :set list, too.

Pasting large amounts of text into Vim

Every Vim user likes to enable auto-indenting of source code, so Vim can intelligently position you cursor on the next line as you type. This has one big ugly consequence however: when you paste text into your terminal-based Vim with a right mouse click, Vim cannot know it is coming from a paste. To Vim, it looks like text entered by someone who can type incredibly fast :) Since Vim thinks this is regular key strokes, it applies all auto-indenting and auto-expansion of defined abbreviations to the input, resulting in often cascading indents of paragraphs.

There is an easy option to prevent this, however. You can temporarily switch to “paste mode”, simply by setting the following option:

set pastetoggle=<F2>

Then, when in insert mode, ready to paste, if you press <F2>, Vim will switch to paste mode, disabling all kinds of smartness and just pasting a whole buffer of text. Then, you can disable paste mode again with another press of <F2>. Nice and simple. Compare paste mode disabled vs enabled:

Another great trick I read in a reddit comment is to use <C-r>+ to paste right from the OS paste board. Of course, this only works when running Vim locally (i.e. not over an SSH connection).

Enable the mouse

While using the mouse is considered a deadly sin among Vim users, there are a few features about the mouse that can really come to your advantage. Most notably—scrolling. In fact, it’s the only thing I use it for.

Also, if you are a rookie Vim user, setting this value will make your Vim experience definitively feel more natural.

To enable the mouse, use:

set mouse=a

However, this comes at one big disadvantage: when you run Vim inside a terminal, the terminal itself cannot control your mouse anymore. Therefore, you cannot select text anymore with the terminal (to copy it to the system clipboard, for example).

To be able to have the best of both worlds, I wrote this simple Vim plugin: vim-togglemouse. It maps <F12> to toggle your mouse “focus” between Vim and the terminal.

Small plugins like these are really useful, yet have the additional benefit of lowering the barrier of learning the Vim scripting language. At the core, this plugin exists of only one simple function:

fun! s:ToggleMouse()
    if !exists("s:old_mouse")
        let s:old_mouse = "a"
    endif

    if &mouse == ""
        let &mouse = s:old_mouse
        echo "Mouse is for Vim (" . &mouse . ")"
    else
        let s:old_mouse = &mouse
        let &mouse=""
        echo "Mouse is for terminal"
    endif
endfunction

Get efficient: shortcut mappings

The following trick is a really small one, but a super-efficient one, since it strips off two full keystrokes from almost every Vim command:

nnoremap ; :

For example, to save a file, you type :w normally, which means:

  1. Press and hold Shift
  2. Press ;
  3. Release the Shift key
  4. Press w
  5. Press Return

This trick strips off steps 1 and 3 for each Vim command. It takes some times for your muscle memory to get used to this new ;w command, but once you use it, you don’t want to go back!

I also find this key binding very useful, since I like to reformat paragraph text often. Just set your cursor inside a paragraph and press Q (or select a visual block and press Q).

" Use Q for formatting the current paragraph (or selection)
vmap Q gq
nmap Q gqap

If you are still getting used to Vim and want to force yourself to stop using the arrow keys, add this:

map <up> <nop>
map <down> <nop>
map <left> <nop>
map <right> <nop>

If you like long lines with line wrapping enabled, this solves the problem that pressing down jumpes your cursor “over” the current line to the next line. It changes behaviour so that it jumps to the next row in the editor (much more natural):

nnoremap j gj
nnoremap k gk

When you start to use Vim more professionally, you want to work with multiple windows open. Navigating requires you to press C-w first, then a navigation command (h, j, k, l). This makes it easier to navigate focus through windows:

" Easy window navigation
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l

Tired of clearing highlighted searches by searching for “ldsfhjkhgakjks”? Use this:

nmap <silent> ,/ :nohlsearch<CR>

I used to have it mapped to :let/=“”, but some users kindly pointed out that it is better to use:nohlsearch@, because it keeps the search history intact.

It clears the search buffer when you press ,/

Finally, a trick by Steve Losh for when you forgot to sudo before editing a file that requires root privileges (typically /etc/hosts). This lets you use w!! to do that after you opened the file already:

cmap w!! w !sudo tee % >/dev/null

Other cool plugins

In order to make the article not any more longer than it already is, here’s a list of other plugins that are really worth checking out (I use each of them regularly):

  • localrc: lets you load specific Vim settings for any file in the same directory (or a subdirectory thereof). Comes in super handy for project-wide settings.

  • CtrlP: lets you open files or switch buffers quickly using fuzzy search. I'd highly recommend it.

Other resources

Some of the resources from where I have collected inspiration for my .vimrc file, plugins, and tricks:

I hope you like these tips. You can have a look at my full Vim configuration in my Github repo.

Other posts on this blog

If you want to get in touch, I'm @nvie on Twitter.