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
.vimrcfrom an online article. - Don't be afraid to ask Vim for :help.
- Keep your
.vimrcin 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
.vimrcs you might miss important details.
Modernising vim & making it more sensible
Most .vimrcs contain some settings to smooth over some foibles and legacy features:
set nocompatibletells Vim to forget about Vi compatibility. Interestingly, as soon as you create a~/.vimrcthis option gets set automatically.set hiddenallows for hidden buffers - basically stopping Vim whining when you open more than one file.set ttyfastmight also be on by default, depending on your$TERMenvironment variable. When on, Vim will update your screen in bigger batches.set backspace=indent,eol,startenables backspacing over everything, like every modern editor ever.nmap j gjandnmap k gkmakej /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=markdownsetsfoo.mdfiles 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
endautomatically 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 numberto always show line numbers andset relativenumberto 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.gitignorefile. You can tell Vim to useagfor 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 ""' endifScreen 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=2determines 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 autoreadwill reload the file if it changes. It's nottail -f, though: you have to run a shell command or invoke:checktimeto 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
.vimrcto automatically set up hisvirtualenv. I'd keep this in a dedicated script and call it from the.vimrcinstead. set nostartoflinekeeps 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 cursorlineto 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.