How I boosted my Vim
nvie.com/posts/how-i-boosted-my-vim/
Published: September 14, 2010
Published: September 14, 2010
Last updated: September 23, 2010 (highlight updates)
Last updated: September 23, 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
Oh, and man… never ever let Vim write a backup file! They did that in the 70’s. Use modern ways for tracking your changes, for God’s sake.
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:
- Press and hold Shift
- Press
;
- Release the Shift key
- Press
w
- 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 @/=""<CR>
, 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
Use plugins
Ah, finally. Arrived at the magical stuff that is Vim plugins. This is a listing of the Vim plugins I depend on most and that really offer added value when you work with Vim every day.
Almost any person I know who owns a Mac has at least tried or purchased the TextMate editor. It is a great programmer’s editor that has a lot of nice features, but of course, lacks Vim-style navigation :)
Some of its features have inspired Vim plugin developers to clone the awesomeness. TextMate’s best two features (super-quick file opening and snippets) have been “ported” to Vim plugins.
Command-T: TextMate-style file opening NERDTree explorer
The NERDTree plugin is an absolute must for almost any Vim user. For those who don’t know it yet, NERDTree is a visual file browser that allows you to quickly open files by navigating onto it and pressing Return.
You can open the NERDTree using the :NERDTree
command, or by using
:NERDTreeToggle
. To close the tree window, use :NERDTreeClose
.
I have I’ve mapped some shortcuts to these commands, for quick access to the list:
nmap ,n :NERDTreeClose<CR>:NERDTreeToggle<CR>
nmap ,m :NERDTreeClose<CR>:NERDTreeFind<CR>
nmap ,N :NERDTreeClose<CR>
You can add quick bookmarks to directories that you often visit (like project directories), which works really well. I have configured the following settings, which tells the plugin where the bookmark file is, which extensions to ignore, to show hidden files and to quit on open (which I like to have on, to have screen real estate for my code):
" Store the bookmarks file
let NERDTreeBookmarksFile=expand("$HOME/.vim/NERDTreeBookmarks")
" Don't display these kinds of files
let NERDTreeIgnore=[ '\.pyc$', '\.pyo$', '\.py\$class$', '\.obj$',
\ '\.o$', '\.so$', '\.egg$', '^\.git$' ]
let NERDTreeShowBookmarks=1 " Show the bookmarks table on startup
let NERDTreeShowFiles=1 " Show hidden files, too
let NERDTreeShowHidden=1
let NERDTreeQuitOnOpen=1 " Quit on opening files from the tree
let NERDTreeHighlightCursorline=1 " Highlight the selected entry in the tree
let NERDTreeMouseMode=2 " Use a single click to fold/unfold directories
" and a double click to open files
You can add quick bookmarks to directories that you often visit (like project directories), which works really well, too.
More documentation available at: the plugin page.
I used to have a whole discussion on the NERDTree explorer plugin here, but I was pointed towards Command-T by a few readers. Once I tried that plugin for a few minutes, it became clear that there would be no need for NERDTree anymore.
The name Command-T is a reference to the original shortcut for “Go to File” in TextMate, which opens the quick file opener. Setting up this plugin is a bit more tricky than usual, because some files need to be compiled, but the instructions on the website are very clear and simple. There’s even a screencast for Windows users.
The plugin registers itself under <leader>t
(in my case that’s ,t
). And if
it does, it shows a list of all the files from the current directory and a
search box in which you can type any character progression. By typing more
characters, the list of files is narrowed down to contain only files that have
that string as a subset. But here’s the real added value: you can type any
sequence of characters that are in the file’s path, they don’t have to be
subsequent characters. For example, if you have the following list of files:
foo/bar.py
foo/qux.py
tests/test_foo/test_bar.py
tests/test_foo/test_qux.py
You could type the sequence fb to select the file foo/bar.py
, or tfb to
select tests/test_foo/test_bar.py
. As you can imagine, this is a huge time
saver. There is much more goodness in there. For that, please refer to
Wincent’s screencasts, or his website.
You can download the plugin at vim.org.
Note: On Vim instances that don’t have Ruby support enabled (type :version
to check this), the Commant-T plugin won’t work. If it isn’t an option to
recompile Vim to add Ruby support, the NERDTree
explorer still is a good
alternative.
Snipmate: TextMate-style snippets for Vim
Another killer feature of TextMate are the intelligent snippets: you type some text, press Tab and TextMate creates a snippet for you, with placeholders at key positions within the snippet. The first placeholder is selected, your overwrite it with the text you want, then press Tab to select the second placeholder, etc. This lets you enter code super fast.
Now it’s available to us Vim users, too, in the form of the snipMate plugin (dubbed after TextMate). There’s a great introductory screencast to get you excited about it.
Writing your own snippets
There are already lots of specific language plugins
snippets for snipMate
available, but writing your own is simple in case you ever miss functionality.
Just create a file called ~/.vim/snippets/foo.snippet
, where foo
is the
filetype you want to load the snippets for.
Then, declare your snippets. That’s really as easy as this:
snippet def
def ${1:fname}(${2:arg}):
${3:pass}
If you declare this, you can simply use def<Tab>
and it will expand to a
Python function definition. The ${1:fname}
means "put the first placeholder
at this position, and fill it with a default value of “fname”.
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.
- Sparkup: write HTML lightning fast by jotting down a “CSS selector”-like line and pressing a shortcut. Super time saver when you edit HTML manually. Go see the demo video.
- YankRing: quickly cycle through your registers when pasting, to select the appropriate paste. How often have you “cut” a line, then “deleted” a line, only to find the “deleted” line in your last paste register?
- Pastie: lets you visually select a piece of code and submit it to pastie.org. It even has automatic filetype recognition.
-
surround: quickly
change surroundings of a piece of code. For example, to change
dict(mykey)
intodict[mykey]
, put the cursor onmykey
, then typecs(]
(change surroundings from()
to[]
). -
repeat: lets you
repeat the changing of surroundings using the default Vim repeat operator
.
(dot). -
abolish: bulk-define
autocorrections (abbreviations) for many conjugations of words and smart
conversion of words from snake_case (
crs
) to camelCase (cr_
) or MixedCase (crm
) to UPPER_CASE (cru
) and vice versa. - LustyJuggler: a quick buffer switcher and a great companion to Command-T. See this screencast (Lococast) to get excited.
Other resources
Some of the resources from where I have collected inspiration for my .vimrc
file, plugins, and tricks:
- Vimcasts
- Lococast
- Derek Wyatt’s videos (on Vimeo)
- Steve Losh blogged about moving back to Vim and has some great tips and tricks.
I hope you like these tips. Please add your comments below if you do, or if you have any Vim improvements or tips you’d like to bring on yourself. You can have a look at my full Vim configuration in my Github repo.
If you want to get in touch, I'm @nvie on Twitter.