On Vim
I’ve been using Vim in various settings (in my IDE, in the terminal, in Obsidian, to prepare LaTeX documents, …) for a few years now. This post exists mainly to share my favourite Vim commands/resources, however also give a bit of advice on the process of learning Vim.
How to learn Vim
There are some good resources about to help you learn Vim which I’ll link below. In terms of best practices to aid your learning, I have two main bits of advice.
Firstly, it can be more pleasant to start in a text editor which supports Vim but also allows mouse-based interaction and other non-Vim paradigms. For me this happened by accident since I started using Vim in PyCharm with the IdeaVim plugin, but this is also possible in, for eg, MacVim (only for Mac users), and Obsidian with the Vim plugin enabled. It might not be optimal for learning to be able to opt-out of using Vim syntax sometimes, however it will allow you to integrate Vim into your workflow gradually, thus lowering the barrier to entry, and decreasing the chance you give up altogether. The idea of course is that over time you use proportionately more and more Vim commands, until using the mouse becomes less efficient and you stop altogether.
Secondly, and in slight opposition to the above, you must be willing to suffer
an initial drop in productivity and rise in frustration. When I first switched
on IdeaVim in PyCharm I spent a while getting very confused and annoyed when
either Vim didn’t behave as expected, or when my now-outdated muscle memory from
pre-Vim days misled me. The only real way through this is practice and
perseverance: take the time to Google Vim-based ways of doing whatever it is you
were trying to do, and if a command isn’t functioning as you expect, take the
time to find out why. One case of this for me (among many) was not realising
that having caps lock enabled totally changes the meaning of many Vim commands
– eg D
is the same as dd
.
Vim commands I like
These commands straddle difficulties, though there’s nothing particularly
advanced here. This section presumes basic knowledge of Vim and its syntax. Note
<char>
here represents a character on the keyboard, eg a
, [
, .
, … Note
also that anywhere I use +
, it is to indicate concatenation of commands,
rather than the literal plus symbol.
Editing
di<char>
, where<char>
is a ‘paired’ character (eg{
,[
,'
etc) will delete inside the paired character (so{name: int}
would become{}
). This has as special casesdib
anddiB
, which are equivalent todi(
anddi{
respectively. As with all such commands,ci<char>
will do the same but enter insert mode,yi<char>
will yank, etc~
can be used to toggle case either for the character under the cursor if in normal mode, or for selected characters if in visual modegq<motion>
reformats anything with in the scope of<motion>
(eggqG
reformats from the current line to the bottom), with the special casegqq
which reformats the line. I find this super useful for writing these articles, as I do so in Obsidian, which isn’t good at line breaks – I can justgq
the doc once it’s in Vim proper and it gets fixed. (Note sometimes it can be a bit over-zealous in what it fixes, so I wouldn’t use indiscriminately.)- (Requires Surround.vim – see below
for some stuff about plugins.)
ysw<char>
will surround to the end of the current word with<char>
– if in the middle of a word you will probably want to useb
to go to the start of the word first. This extends as you’d expect, egys$<char>
is the same but for the whole line. Note<char>
must be a ‘paired’ character as above - Following on from the above,
ds<char>
will deleted paired<char>
s ctrl + v
will enter ‘multi-cursor’ mode. A common use-case for me isctrl + v
, thenj
to select a bunch of lines,I
to enter insert mode (this will only show on the first selected line), thenesc
when done to apply the changes to all selected lines- You can record macros by pressing
q<char>
to start recording, then typing the command for the macro, then pressingq
when done. To use the macro type@<char>
(as with all Vim, this accepts a number of iterations, eg10@a
repeats the command stored in thea
register 10 times) .
repeats the last command>>
indents a line – powerfully combines with visual modeg??
scrambles a line, respecting word length (not sure of applications, but it’s fun)
Motion
f<char>
moves the cursor the next occurrence of<char>
on the line.F
moves the cursor to the most recent previous such occurrence on the line. This can be combined very powerfully withd
– egdf:
deletes inclusively to the next colont<char>
moves the cursor to the character before the next occurrence of<char>
, as above forT
. Again can be combined very powerfully withd
/string
will search the file for the next occurrence ofstring
. You can toggle through them withn
%
moves the cursor to the paired character matching the one under the current cursor (if one exists)- You can set a marker at register
<char>
by typingm<char>
: when you type`<char>
it will move to where you placed the marker. Relatedly,'<char>
takes you to the start of the marker’s line
My .vimrc
Some of this might be useful/interesting. It’s fairly basic as .vimrc
s go, as
I haven’t really defined any custom commands, but for now I find it does the
job. Feel free to copy any bits you find useful (that’s probably how I ended up
with them in the first place).
One or two bits merit explanations/warnings:
- I use the
vim-plug
plugin manager (guide here) – you will need to install it before you’ll be able to use the below.vimrc
vimtex
is a wonderful plugin for Vim/LaTeX – for a great guide on this topic and more see here- The typeface bit possibly (I did on OS X, I didn’t on Ubuntu) requires you to install ‘DejaVu Sans Mono for Powerline’ (this is needed for the theme) – you can see a guide on this here
- If you have spellcheck enabled, you can add a word to the dictionary with
zg
(neat right?) - The tabbing stuff enables auto-mapping to tabs to spaces, as well as a few other niceties such as auto-line breaking at 80 chars. The stuff below makes Vim show me trailing whitespace, tabs, and other undesirable characters
- I make no apology for leaving the mouse sometimes enabled – sometimes I come to Vim briefly from a non-Vim context, and it can just make things easier (eg for copying and pasting text outside of Vim – you can configure some settings to do this, but how to do so differs by OS and Vim version)
scriptencoding utf-8
call plug#begin('~/.vim/plugged')
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'scrooloose/nerdtree'
Plug 'lervag/vimtex'
Plug 'tpope/vim-surround'
call plug#end()
" font
set guifont=DejaVu\ Sans\ Mono\ for\ Powerline
" theme
let g:airline_theme='deus'
let g:airline_powerline_fonts = 1
" utf-8 encoding
set encoding=utf-8
" spellcheck
set spell spelllang=en_us
" basic tabbing stuff
set expandtab
set tabstop=4
set softtabstop=4
set shiftwidth=4
set autoindent
set textwidth=80
" whitespace
set listchars=tab:>-,trail:·,extends:>,precedes:<
set list
" function to strip whitespace on save
function! <SID>StripTrailingWhitespaces()
let l = line(".")
let c = col(".")
%s/\s\+$//e
call cursor(l, c)
endfun
autocmd BufWritePre * :call <SID>StripTrailingWhitespaces()
" show line numbers
set number
" no noises when wrong
set visualbell
" always allow mouse
if has('mouse')
set mouse=a
endif
Other Vim resources
There are loads of other Vim resources out there; I’ll list a few here.
- If you type
vimtutor
on your command line (if you have Vim installed) it should start a Vim tutorial, which is a great way of getting acquainted with the basics - Learn to speak Vim
- Great StackOverflow answer about Vim