Vim

Vim is a terminal-based editor optimized for speed. Keys are hotkeys by default. Vim does not even use Ctrl for most of them. Maneuvering via hotkeys is so efficient mouse input is often disabled by default.

This guide focuses on the features I use most frequently. It has nothing about with native Vim windows because I use i3 or Spacemacs instead. If you feel I left out a valuable feature then please let me know about it in the comments.

Movement

The simplest way to move is via the hjkl keys.

key action
h moves the cursor one character left
j moves the cursor one line down
k moves the cursor one line up
l moves the cursor one character right

The hl keys operate within a single line. Pressing h at the start of a line does nothing. Pressing l at the end of a line does nothing. By line I mean a string of characters ending with a carriage return. The fact that a long paragraph appears to wrap around on your screen is irrelevant.

The jk keys move the cursor down and up a single line. If the cursor is in the 3rd column of the 6th line then pressing j moves the cursor to the 3th column of the 7th line.

Most commands can be prefixed with a number.4h moves the cursor left 4 characters.101j moves the cursor down 101 lines.

A sequence of nonempty lines is called a paragraph. The {} keys move the cursor forward and back by paragraphs.

key action
} moves the curser forward one paragraph
{ moves the curser backward one paragraph

There are two kinds of “words” in Vim. A word is a sequence of alphanumeric characters. A Word is a sequence of non-whitespace characters. The wbe keys move the cursor around words. The WBE keys move the cursor around Words.

key action
w moves the cursor forward to the next start of a word
e moves the cursor forward to the next end of a word
b moves the cursor backward to the next start of a word
W moves the cursor forward to the next start of a Word
E moves the cursor forward to the next end of a Word
B moves the cursor backward to the next start of a Word

The #* keys move the cursor forward and backward to the next “idenfitier”. If the cursor hovers over the word “marmot” then pressing * will move the cursor forward to the next instance of the word “marmot” and pressing # will move the cursor backward to the previous instance of the word “marmot”.

key action
# moves the cursor backward to the previous identifier
* moves the cursor forward to the previous identifier

The f key takes a character as an argument and moves the cursor forward to that character. For example, fa moves the cursor forward to the next instance of a. The f key operates within a line. It will never take the cursor to another line. The F command is like f except it searches backward. The t and T commands are like f and F exvcept they move the cursor one fewer character.

The ; command repeats the most recent fFtT command. The , command is like ; except backwards. If you use an F command followed by a , then the double-backwardsness will cancel itself out.

key action
f<char> moves forward to <char>
F<char> moves backward to <char>
t<char> moves forward to the character before <char>
T<char> moves backward to the character after <char>
; repeats the previous fFtT command
, repeats the previous fFtT command except reversed

The 0^$ keys move the cursor to the beginning and end of a line.

key action
0 moves the cursor to the beginning of the line
^ moves the cursor to the beginning of the line, excluding whitespace
+ moves the cursor to the beginning of the next line, excluding whitespace
$ moves the cursor to the end of the line

The HLM keys move the cursor around relative to the viewing window itself.

key action
H moves the cursor the the start of the first visible line
M moves the cursor the the start of the middle visible line
L moves the cursor the the start of the last visible line

You can move the viewing window itself with z and Ctrl keys.

key action
Ctrl-e moves the viewing window down one visual line
Ctrl-y moves the viewing window up one visual line
Ctrl-f moves the viewing window forward by one viewing window
Ctrl-b moves the viewing window backward by one viewing window
Ctrl-d moves the viewing window forward by half of one viewing window
Ctrl-u moves the viewing window backward by half of one viewing window
zz moves the viewing window to position the cursor in the middle
zt moves the viewing window to position the cursor at the top
zb moves the viewing window to position the cursor at the bottom

You can move the cursor itself up and down visible lines with the g prefix.

key action
gj moves the cursor down one visual line
gk moves the cursor up one visual line

The g key can also go to a particular line.

key action
gg jumps the cursor to the beginning of the buffer[1]
G jumps the cursor to the end of the buffer
<num>gg jumps the cursor to the beginning of the buffer
<num>G

The | key is like g except for columns.

key action
<num>| moves the cursor to the <num>th column within a line

The / key performs search. You type / then the string you are searching for and then press Enter. The ?nN keys are analogous to F;n.

key action
/​ initiates a search
? initiates a backwards search
n repeats the previous search
N repeats the previous search except reversed

The () characters move forward and backward one sentence.

key action
) moves forward to the next start of a sentence
( moves backward to the next start of a sentence

The [] characters move the cursor forward and backward to a variety of things. My favorite uses of [] is to go forward and backward to matching parenthesis. For example, ]) moves forward to the next unmatched closing parenthesis. It is indispensable when writing Lisp. Inner quotes and tags behave similarly to parentheticals.

key action
]) move forward to matching parenthesis
](
[) move backward to matching parenthesis
[(
[[ jump to function start
]] jump to function end

You can (invisibly) mark places in your buffer to return to later. You can set one mark per letter. Lowercase letters a-z are buffer-specific e.g. each buffer can have its own “a” mark. Uppercase letters A-Z are global e.g. only one buffer at a time can have an “A” mark.

key action
m<a-z> create a buffer-specific mark
m<A-Z> create a global mark
’<mark> jump to the beginning of the line with mark <mark>
`<mark> jump to mark <mark>

Some marks are populated automatically. Of the automatic marks, I only use ''. You can find the others here.

mark meaning
jump to last jump point

Editing

Now that you know how to move, we can edit some text. Most of the time you edit text you should use the dyp keys.

  • d stands for delete, which is similar to “cut”.

  • y stands for yank, which is similar to “copy”.

  • p stands for put, which is similar to “paste”.

The d key operates on text objects and movement commands. For example dtA deletes everything up to (but not including) the next “A” on the current line.

Every delete operation operates on characters or lines.dtA operates on characters and thus behaves similarly to other editors. A delete operation which operates on lines deletes an integer number of lines. Delete operations which operate on lines delete the current line and the destination line. Thus, dj deletes the current line and the next line.

y is identical to d except it leaves your buffer unchanged.

delete or yank key action
d<char> deletes every character from the starting character up to (and including) the destination character
d<line> deletes every line from the starting line up to (and including) the destination line
dd deletes the current line
y<char> yanks every character from the starting character up to (and including) the destination character
y<line> yanks every line from the starting line up to (and including) the destination line
yy yanks the current line

p puts the selection before the cursor.P puts the selection after the cursor. “Before” and “after” refer to characters or lines depending on whether you deleted/​yanked characters or lines.

key action
p put before the cursor
P put after the cursor

By default, p and P will put the last text you deleted or yanked. You can save text into registers by prefixing "<register> before your delete or yank command. For example, "add deletes the current line and saves it into register “a”.

There is one register for each letter a-z. If you use a capital letter then your delete or yank command will append to the register instead of overwriting it. You can put from a register by prefixing your p or P command with the register. For example, "ap" will put from register “a”.

You can find a list of special registers here.

Text Objects

Remember how I said you could follow d and y with a movement command or a text object? Remember from earlier the concept of “words” and “paragraphs”? Here we put them together into a simple grammar.

da deletes a text object.

key action
daw delete a word
daW delete a Word
das delete a sentence
dap delete a paragraph
da( delete a parenthetical
da)
yaw yank a word
yaW yank a Word
yas yank a sentence
yap yank a paragraph
ya( yank a parenthetical
ya)

You can replace the a with an i to delete an inner word, an inner paragraph, etcetera. An inner text object is just like the regular text object except it does not include any surrounding delimiters. In the case of a parenthetical, the “inner parenthetical” does not include the outside parenthesis. For words/​sentences/​paragraphs, the delimiter is whitespace.

key action
diw delete inner word
diW delete inner Word
dis delete inner sentence
dip delete inner paragraph
di( delete inner parenthetical
di)
yiw yank inner word
yiW yank inner Word
yis yank inner sentence
yip yank inner paragraph
yi( yank inner parenthetical
yi)

Other text objects include '"[]{}<>. They all do what you would expect them to do.t refers to an HTML-like tag.

Insert Mode

You cannot write everything by yanking and putting pieces of existing text together. Sometimes you have to insert text into a document. Several different keys drop you into insert mode.

key action
i inserts text before the cursor
a inserts text after the cursor
I inserts text at the beginning of the line
A inserts text at the end of the line
o creates a newline below the current line and inserts text there
O creates a newline above the current line and inserts text there
s deletes the current character and inserts text
S deletes the current line and inserts text

You can exit insert mode by pressing Escape but it is faster to remap your CapsLock key to Ctrl and then exit insert mode with Ctrl-[. Some hotkeys are valid only while in insert mode.

insert mode key action
Escape exits insert mode
Ctrl-[
Ctrl-F moves cursor forward one character
Ctrl-b moves cursor backward one character
Ctrl-w deletes one word backward (without saving it to a register)

The c key is like d except it drops you into insert mode afterward.

key action
c<movement> clear text
c<text_object> clear text

After you exit insert mode, the whole insertion counts as a single edit. So if you type ci( followed by an insertion then the entire replacement of text inside the parenthetical counts as a single edit. You can repeat an edit with the . operator.

key action
. repeat previous edit

The . key might be the most important key in all of Vim. Generally-speaking, the more you use the . operator the better you are at Vim.

Miscellaneous edit commands

key action
x delete the character under the cursor
X delete the character before the cursor
~ toggle capitalization and move the cursor forward one character
r<char> replace a single character

The Undo Tree

u and Ctrl-r operate like the undo and redo stack you are familiar with.

key action
u undo last edit
Ctrl-r redo next edit

If you undo a long series of edits and then mistakenly make an edit you can undo the damage with g+ and g- which traverse the nodes of the tree in chronological and reverse-chronological order.

key action
g+ traverse undo tree in chronological order
g- traverse undo tree in reverse chronological order

Macros

A macro is a series of keystrokes. Macros are good for automating repetitive tasks, especially editing structured text.

To define a macro, start by pressing the q key. Then pick a letter a-z at which to save the macro. Then execute the macro manually. When you are done typing the macro, press q again.

Once you have a macro defined, you can press @ followed by the macro’s letter to execute the macro.

key action
q define a macro
@<a-z> execute a macro
@@ execute previous macro

Macros are well-behaved. If a macro modifies a line and then goes down one line and you tell Vim to execute the macro 1000 times but your buffer only has 700 lines then Vim will stop when it gets to the end of your buffer.

Visual mode

Visual modes are similar to highlighting. Visual modes have their uses, but it is usually faster to avoid them.

key action
v enter visual mode
V enter visual line mode
Ctrl-v enter visual rectangle mode

Find and Replace

You can find and replace all the instances of a string by typing :%s/ followed by the original string followed by / followed by the replacement string followed by Enter…assuming you did not type any escape sequences. Find and replace is a complex subject I will not delve into here even though I do use it.

Enter and exit

You can enter Vim by typing vim into your terminal followed by the file you would like to create or edit. You can exit vim by typing : followed by a quit command.

command action
:q exit if no changes are pending
:q! force an exit even if changes are pending
:w write to disk
:wq write to disk and then exit

Typing ZZ does the same thing as the :wq command.

Cheatsheet


  1. If you are not from a Unix back then the term “buffer” may be unfamiliar. Just translate “buffer” to “file” or “document” in your head even though, technically, a buffer is more general than a document. ↩︎