Last week, I gave a talk at Vim London about Vim's configuration file. We examined my .vimrc, Nic West's, Tim Mower's, Arturo Herrero's, James Cooke's, and Oliver Caldwell's. We also had a look at Drew Neil's during the Q&A.
The basics
Vim reads a configuration file called ~/.vimrc
when it starts. You don't have to keep all your configuration in one file; several people put settings in other files (such as ~/.vim/bundle
) and add source ~/.vim/bundle
to their .vimrc
. You can run vim -u filename
to read a different settings file; nobody at the meeting used that, but some people use it to manage different settings across projects. You can do this automatically with set exrc
and set secure
.
Good habits
- Add a comment with a URL when copying settings to your
.vimrc
from an online article. - Don't be afraid to ask Vim for :help.
- Keep your
.vimrc
in source control. As well as keeping track of what you add and remove, it makes it easier to keep your files in sync between several different machines (such as home & work). - Bind your most used commands to the
Fx keys; they're unused in Vim, so are free for your own use. - Use a tool to manage your Vim plugins; Vundle is preferable to Pathogen because it saves you from the horrible world of Git submodules.
- Remember that Github won't show non-printable characters, so if you're browsing
.vimrc
s you might miss important details.
Modernising vim & making it more sensible
Most .vimrc
s contain some settings to smooth over some foibles and legacy features:
set nocompatible
tells Vim to forget about Vi compatibility. Interestingly, as soon as you create a~/.vimrc
this option gets set automatically.set hidden
allows for hidden buffers - basically stopping Vim whining when you open more than one file.set ttyfast
might also be on by default, depending on your$TERM
environment variable. When on, Vim will update your screen in bigger batches.set backspace=indent,eol,start
enables backspacing over everything, like every modern editor ever.nmap j gj
andnmap k gk
makej /k move the cursor up/down by lines on the screen, not lines in the file. Navigation feels more natural when using word wrap this way.au BufRead,BufNewFile *.md set filetype=markdown
setsfoo.md
files to be Markdown, not Modula2.- You can get better tab completion for Vim commands if you
set wildmenu
. You may also like toset wildmode=list:longest
, and you can ignore certain files - like Python compiled files - withset wildignore=*.pyc
. - You can set a mark in Vim with
m a , and jump back to that line with' a . If you want to back to that exact cursor position, you can use` a , but that's harder to press. You can swap` and' withnnoremap ' `
andnnoremap ` '
. - Normally Vim will scroll the screen when the cursor hits the first/last line. You can make it scroll 3 lines earlier with
set scrolloff=3
. Nic went as far as toset scrolloff=15
.
Views & Sessions
Vim supports views, which save the cursor position & code folds between editing sessions (along with a few other settings). I've used an autocommand to automatically save and load a view whenever I edit a file:
au BufWinLeave ?* silent mkview
au BufWinEnter ?* silent loadview
Vim also has a sessions feature, which saves the whole editing session - everything in the views, along with the open buffers, window layout, tabs, etc. Oliver has bound
nnoremap <F7> :mksession! .quicksave.vim<CR>
nnoremap <F8> :source .quicksave.vim<CR>
I recommended he move them to non-neighbouring keys, to make it harder to accidentally hit the wrong key & save an empty session.
Plugins and other tools
The most interesting plugins were:
- CtrlP, a fuzzy-finder for navigating projects.
- Vim-endwise, to add
end
automatically in Ruby. - Vim-numbertoggle will show you relative line numbers in normal mode and absolute line numbers in insert mode. This makes it easier to write multiple line-spanning motions. You can use
set number
to always show line numbers andset relativenumber
to always show relative numbers. - Vim-unimpaired adds some navigation commands to the
[ ] keys. - Easymotion turns motions into a multiple-choice option.
Some tools that people use with Vim include:
Ack (and the similar Ag, AKA "The Silver Searcher"). They're
grep
-like tools that have useful features like respecting your.gitignore
file. You can tell Vim to useag
for its built-in grep, as well as telling CtrlP to use it too:if executable('ag') set grepprg=ag\ --nogroup\ --nocolor let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""' endif
Screen and tmux remain popular. Plugins like vim-tmux-navigator and tmuxline provide some Vim integration.
Git is used by everyone for source control, often with the vim-fugitive plugin.
Search and search highlighting
Vim can highlight search results as you type:
set hlsearch
set incsearch
set ignorecase
makes searching case insensitive; set smartcase
makes searching case insensitive unless you use any capital letters. If you find yourself using substitutions a lot then you might want to set gdefault
to make replacement global without having to add the g
flag.
Refreshing
I've found that Vim sometimes messes up syntax highlighting or forgets the filetype. I've bound
noremap <F5> <esc>:syntax sync fromstart<cr>:filetype detect<cr>
inoremap <F5> <esc>:syntax sync fromstart<cr>:filetype detect<cr>a
Oliver used his
command! GenerateTags call system('ctags -Rf ./.tags --python-kinds=-i --exclude=.git `cat .srclist`') | echo
nnoremap <F5> :GenerateTags<CR>
You could combine these if you wanted to.
Swapfiles, backups, and undo
Vim can create backups when you write files, save your undo history between sessions, and uses a swap file to track changes when running.
Just about everybody tells Vim to put these files in their own directories. At the very least, you won't have to add them to your .gitignore
files that way:
set undodir=~/.vim/tmp/undo/
set backupdir=~/.vim/tmp/backup/
set directory=~/.vim/tmp/swap/
It seems like a good idea to make those directories if they don't already exist:
if !isdirectory(expand(&undodir))
call mkdir(expand(&undodir), "p")
endif
if !isdirectory(expand(&backupdir))
call mkdir(expand(&backupdir), "p")
endif
if !isdirectory(expand(&directory))
call mkdir(expand(&directory), "p")
endif
Turn on persistent undo with set undofile
. Turn backups on with set backup
. Some people turn off swapfiles with set noswapfile
; Vim speeds up, but you're promising that Vim will always shut down cleanly & you'll never open the same file in two different Vim instances.
Avoiding the escape key, and other personal taste issues
Some people like to avoid the escape key, and use keystrokes like
noremap <Esc> <Nop>
inoremap jk <Esc>
inoremap jj <Nop>
We also mentioned the influence of the ADM-3A, a common terminal used when Vi was written. Its ~
as a shortcut for the home directory. It also had arrows on
James' .vimrc
swapped :
for ;
, to cut down on
nnoremap ; :
nnoremap : ;
But James recommended against this, as when he uses other programs with Vim mappings his muscle memory is basically useless.
Obeying coding conventions
If your coding style guide specifies a maximum line length, you can set colorcolumn=80
to add a stripe at the 80 column mark.
You can show hidden characters (like trailing whitespace and tabs) with custom symbols. Here's James':
set list
set listchars=eol:¬,tab:â–·\ ,
Shortcuts for stripping trailing whitespace were also popular: nnoremap <F2> :%s/\s\+$//e<CR>
Micro-optimisations
If you find yourself performing a repetitive task, it's worth finding a way to optimise it. Nic wrote a function that copies a path to his clipboard, so he could paste it easily into a VM. Tim had a snippet that var_dump()
s the variable under the cursor (a PHP way of printing out variables for debugging): nmap dvd viwy<Esc>odie(var_dump());<Esc>hhP
James likes to use :tabedit
:
nnoremap <C-j> :tabe
The trailing space is important so you can start typing the filename immediately.
Oliver bound leader nnoremap <leader>z 1z=
Arturo added a mapping for :w!!
to save the current file via sudo
:
cmap w!! %!sudo tee > /dev/null %
Highlight words you want to avoid
It's good practice to avoid words like "obviously", "just", & "simply" when writing educational articles. You can use a custom highlighter to make them stand out.
Miscellaneous
set matchtime=2
determines how long Vim will highlight matching brackets, in tenths of a second.- You can use vim folds to hide code in long files by "folding" it up into one line.
- Searching Github for ':wq' gives 7.1 million results.
set autoread
will reload the file if it changes. It's nottail -f
, though: you have to run a shell command or invoke:checktime
to make Vim re-check the file.- James recommended Bare-bones navigation, a previous talk by Kris Jenkins.
- Oliver had an embedded Python program in his
.vimrc
to automatically set up hisvirtualenv
. I'd keep this in a dedicated script and call it from the.vimrc
instead. set nostartofline
keeps the cursor in place when you re-indent code. Sadly, this doesn't move the cursor with the indent so it's not as useful as it sounds.z z moves the line under the cursor to the middle of the screen, which is useful when coding in front of an audience.z t moves the current line to the top. You can also useset cursorline
to underline the current line, which can also help an audience follow along (or a presenter to follow their notes).- Text objects are awesome and you should definitely learn them.
The mysterious pink ping pong balls
After the talk, Tim wrote in about the inoremap <C-R> @@@<Esc>hhkywjl?@@@<CR>P/@@@<CR>3s
lets you use
Thanks to Drew for organising Vim London and to Skimlinks for hosting the meetup.