After 9 years of TextMate, I’m switching to vim
. I’m writing this cheat sheet as I learn. Check back often.
N.B. Keep in mind, everything in vim
is case sensitive.
Modes
In vim
there are six modes:
mode | description |
---|
Normal | For moving around and editing the file |
Insert | For typing text |
Replace | Basically like INSERT mode from DOS, where you overwrite what’s on the screen |
Visual | For selecting characters of text |
Visual Line | For selecting lines of text |
Visual Block | For selecting rectangular blocks of text |
Moving between modes
command | description |
---|
esc or ctrl+[ | Enter Normal mode |
i | Insert at cursor (enters Insert mode) |
I | Insert at the beginning of the line (enters Insert mode) |
a | Insert after cursor (enters Insert mode) |
A | Insert at the end of the line (enters Insert mode) |
R | Overwrite what’s on the screen (enters Replace mode) |
v | Select characters of text, starting at the cursor (enters Visual mode) |
V | Select lines of text, starting with the current line (enters Visual Line mode) |
ctrl+v | Select rectangular blocks of text (enters Visual Block mode) |
gi | Jump to the last place you were in insert mode (enters Insert mode) |
Saving & quitting in normal mode
command | description |
---|
:w | Save (write) |
:q | Quit vim |
:wq | Save & quit |
:q! | Quit without saving changes |
:qa | Close all tabs and quit vim |
:wqa | Write out all work, close all tabs, and quit vim |
ZZ | Same as :wq |
ZQ | Same as q! |
:close | Close the current window (a.k.a., space allocated for a loaded buffer |
Opening files
command | description |
---|
:e filepath | Open a file |
:e! | Reload the current file from disk, discarding changes in memory |
:r filename | Read in and insert a file’s contents inside the current file, at the position of the cursor |
:r !command | Read in the STDOUT of a shell command |
Moving around
command | description |
---|
k | Up |
j | Down |
h | Left |
l | Right |
ctrl+b | Page up |
ctrl+f | Page down |
ctrl+u | Half page up |
ctrl+d | Half page down |
H | Go to the first line on the screen |
M | Go to the middle line on the screen |
L | Go to the last line on the screen |
0 | Beginning of the line |
^ | First non-whitespace character on the line |
$ | End of the line |
w | Go to the beginning of the next word, where punctuation are considered their own word |
W | Go to the beginning of the next word, where spaces separate words |
e | Go to the end of the next word, where punctuation are considered their own word |
E | Go to the end of the next word, where spaces separate words |
b | Go to the beginning of the previous word, where punctuation are considered their own word |
B | Go to the beginning of the previous word, where spaces separate words |
ge | Go to the end of the previous word, where punctuation are considered their own word |
gE | Go to the end of the previous word, where spaces separate words |
( | Go to the beginning of the previous sentence |
) | Go to the beginning of the next sentence |
{ | Go to the beginning of the previous paragraph |
} | Go to the beginning of the next paragraph |
fc | Go to the next occurance of character c on the line |
Fc | Go to the previous occurance of character c on the line |
tc | Same as fc , but one character before it |
Tc | Same as Fc , but one character before it |
; | Next result from fc , Fc , tc , or Tc (don’t try typing these multiple times; use ; to repeat) |
, | Next result from fc , Fc , tc , or Tc in the opposite direction |
% | Jump between the beginning and end of paranthesis, brackets, braces, greater than/less than |
gg | Beginning of the file |
G | End of the file |
:n or nG | Go to line number n |
'. | Go to the last edit |
o | In Visual or Visual Line mode, move your cursor to the other end of the selected area |
O | In Visual Block mode, move your cursor to the other corner of the selected area |
Editing in normal mode
command | description |
---|
x or delete | Delete the character under, and then after, the cursor |
X or backspace | Delete the character before the cursor |
o | Insert line below |
O | Insert line above |
rc | Replace the character under the cursor with character c |
xp | Swap two letters (i.e., delete and paste) |
s | Delete the current character and switch to insert mode (Substitute) |
dw | Delete from the cursor to the end of the word, including the subsequent space |
d) | Delete from the cursor to the beginning of the next sentence |
d} | Delete from the cursor to the end of the current paragraph |
da" | Delete inside quotes, including the quotes |
di" | Delete inside quotes, but leave the quotes |
daw | Delete an entire word, including the subsequent space |
diw | Delete an entire word, but leave the spaces before and after it |
das | Delete a sentence, including the space after the period . |
dis | Delete a sentence, but leave the space after the period . |
dap | Delete a paragraph, including the blank line separating it from the next paragraph |
dip | Delete a paragraph, but leave the blank line separating it from the next paragraph |
dab or da( or da) | Delete an entire parenthetical () block, including the parentheses |
dib or di( or di) | Delete an entire parenthetical () block, but leave the parntheses |
da< or da> | Delete around an angle bracket’s contents <> , including the angle brackets themselves |
di< or di> | Delete inside an angle bracket’s contents <> , leaving the angle brackets |
dat | Delete around an HTML/XML tag <this>and</this> , including the tags |
dit | Delete around an HTML/XML tag <this>and</this> , leaving the tags |
daB or da{ or da} | Delete an entire braces {} block, including the braces |
diB or di{ or di} | Delete an entire braces {} block, but leave the braces |
da[ or da] | Delete a brackets block, including the brackets |
di[ or di] | Dlete a brackets block, but leave the brackets |
cw | Delete from the cursor to the end of the word, excluding the subsequent space, and switch to insert mode |
caw | Delete an entire word, including the subsequent space, and switch to insert mode |
ciw | Delete an entire word, but leave the spaces before and after it, and switch to insert mode |
... | All of the above di* and da* commands work with c instead of d , which will switch to insert mode after the command is run |
cc or S | Delete the current line’s contents, but not the newline, and switch to insert mode (Substitute the current line) |
c$ | Delete to the end of the line, but not the newline, and switch to insert mode |
J | Join the next line to the end of the current line (it deletes the newline character at the end of the current line) |
g | This is one of the hardest vim keystrokes to explain. The formula for using g is g + action + motion. g is useful because you can avoid going into visual mode. Think of it as “go.” For example, gu10j would make 10 lines below the cursor lowercase. If you did this using visual mode, you’d have to type shiftv, 10ju, escape . |
g0 , g^ , or g$ | Like ‘0’, ‘^’, and ‘$’, but respects line wraps |
~ | Toggle the case of the character under the cursor |
u | Change the selected text to lowercase |
U | Change the selected text to uppercase |
Copying and pasting
- Instead of “copying”,
vim
calls it “yanking” - Sometimes instead of “pasting”,
vim
calls it “putting” - I use these terms interchangably, herein
- Unlike Windows, Mac, and Linux, which have one system clipboard for cut and copied text,
vim
has the concept of multiple clipboards called registers. Each register can be yanked into or pasted out of, and is identified with a single character. To accomplish this, prefix the yanking or pasting commands below with "c
, where c
is the register name you wish to yank into or paste out of. For example, "fdd
will delete the current line into the register f
. You could then paste the line by typing "fp
.
command | description |
---|
D | Cuts from the current character to the end of the line to the clipboard |
C | Cuts from the current character to the end of the line to the clipboard, and then switches to insert mode |
dd | Cuts the entire line you’re on to the clipboard |
yy | Copies the entire line you’re on to the clipboard |
y... | Copy any block, like y3w for copy 3 words, or yip to yank inside a paragraph |
p | Paste on the line below the cursor |
P | Paste on the line above the cursor |
ctrl+r, c | Paste in insert mode, from the register c |
"0p | 0 is a somewhat special register that refers to the last explicitly yanked item. This avoids text yanked with D , dd , and other actions that yank as a “secondary” function. "0p will paste the last explicitly yanked item. |
".p | . is another special register: it contains what you last typed. This command will paste from it |
""p | " is another special register: it is the “unnamed” register where text goes if you don’t specify otherwise. This command will paste from it |
"+p | + is another special register: it is the system clipboard |
:reg | View all of the different registers of yanked text |
:set paste | Turn on “paste mode” before you paste from your operating system… |
:set nopaste | … and turn it off when you are done. (I never paste this way; I prefer to use the * register when pasting from OS X, i.e., paste with "*p ) |
Selecting text
command | description |
---|
shift+v | Enter visual mode, selecting the current line; allows additional lines to be selected by using the up and down arrow keys, or j and k ; to select with more granularity, press v |
ctrl+v | Enter visual block mode, where you can select a rectangle of text |
gv | Re-select last selected area |
Indenting
command | description |
---|
= | Fix indentation on selected text |
== | Fix indentation on current line |
> | indent in the selected text by one level |
>> | indent in the current line by one level |
< | indent out the selected text by one level |
<< | indent out the current line by one level |
>a{ | indent a {} block |
>i{ | Indent inside a {} block |
... | Any chunk (paragraphs p , parenthesis ( , tags t , braces { , blocks [ , etc.) can be indented with >a or >i |
Undoing and redoing
command | description |
---|
u | Undo |
:undo | Undo |
:redo | Redo |
ctrl+r | Redo |
Marking (bookmarking)
vim
marks let you mark (or “bookmark”) a character on a line, and return to it later. Each mark can be referenced by a character, like the yanking and macro registers.
command | description |
---|
mc | Mark the cursor’s character, and the line that it’s on, into the mark register represented by character c |
'c | Go to the line that mark c is on |
``c` | Go to the character that mark c is on |
:marks | Show all mark registers |
Searching & replacing
The general formula of searching and replacing in vim
is: range_to_operate_on/regex_to_find/regex_to_replace/regex_options
command | description |
---|
/query | Search from top to bottom. In Visual Mode, select up to the first character of query . |
?query | Search from bottom to top. In Visual Mode, select up to the first character of query . |
n | The “next” thing (i.e., when searching) |
N | The “previous” thing |
* | Go to the next instance of the word under the cursor, or whatever the “next” thing is |
# | Go to the previous instance of the word under the cursor, or whatever the “previous” thing is |
:%s/tofind/toreplace/g | Find & replace in entire file (%s is a range specifying the entire file) |
:%s/tofind/toreplace/ | Find & replace in entire file, but only the first occurance on each line (g at the end replaces all matches on a line) |
:%s/tofind/toreplace/gi | Find & replace in entire file, ignoring case when finding |
:%s/tofind/toreplace/gI | Find & replace in entire file, not ignoring case when finding |
:%s/tofind/toreplace/gc | Find & replace in entire file, confirming before each change |
:%s/tofind/toreplace/ge | Find & replace in entire file, ignoring errors |
:1,10s/tofind/toreplace/g | Find & replace in lines 1 through 10 |
:g/foo/ s/bar/fuzz/g | On lines that contain foo , replace bar with fuzz |
\ | Turn off search highlighting (custom mapping) |
Searching multiple files
command | description |
---|
:vimgrep /^I am/ ./*.markdown | Look for any lines that start with I am in .markdown files in the directory vim was started from |
:vimgrep /^I am/ ./**/*.markdown | Look for any lines that start with I am in .markdown files in the directory, or any subdirectories, vim was started from (i.e., recursive search) |
:cn | Next result from :vimgrep |
:cp | Previous result from :vimgrep |
Repeating commands
In vim
, you can repeat almost any command by prefixing it with a number. For example, k
moves the cursor up by 1 line; 10k
moves the cursor up 10 lines.
command | description |
---|
. | Repeat the last command |
History
- When you open a history window, you can move through commands with arrow keys or
hjkl
- A history window is editable. This means you can use all of the
vim
commands you know and love, like i
to insert or w
to move forward by word. This is a great example of how badass vim
is.
command | description |
---|
q: | Show command history |
q/ or q? | Show search history |
enter | Run the selected command |
ctrl+c, w | Close the history window |
Macros
Macros are a sequence of keystrokes that you can execute automatically.
command | description |
---|
qc | Start recording keystrokes into the c macros register (you can use any character, not just c ) |
q | Stop recording |
@c | Run the macro c |
Abbreviations
Abbreviations in vim
are little snippets that expand when typed, much like TextExpander for OS X. I recommend you set abbreviations in your .vimrc
file.
command | description |
---|
:ab | List all of your abbreviations |
:una shortcut | Unabbreviate (un-register) the shortcut (use this if the shortcut is something you literally wish to type) |
Line numbers
command | description |
---|
:set number | Turn on line numbering |
:set nonumber | Turn off line numbering |
What is the difference between buffers, panes, windows, and tabs?
- A buffer is just that: a buffer of text in memory. When you load a file into vim, a buffer is created for it. A buffer may represent a file on disk.
- A pane is an area on the screen to show a buffer.
- A window is another word for a pane.
- A tab holds one or more panes.
vim
can have multiple tabs.
Buffers
command | description |
---|
:ls | List open buffers. % is the current buffer. # is the alternate buffer (see below). Any buffers with a + are modified and have not been saved to disk. |
:b number | Switch to the buffer with that number in the current pane |
number, ctrl+6 | Switch to the buffer with that number in the current pane |
:b# | Switch to the alternate buffer |
:bn | Switch to the next buffer |
:bp | Switch to the previous buffer |
:bd number | Close the buffer with that number |
Panes
command | description |
---|
ctrl+w, s | Create a horizontal split |
ctrl+w, v | Create a vertical split |
ctrl+w, w | Go to the “next” window |
ctrl+w, arrow key | Put your cursor in the next pane to the left, right, top, or bottom |
ctrl+w, q | Close (quit) a window |
ctrl+w, + | Make the pane taller |
ctrl+w, - | Make the pane shorter |
ctrl+w, > | Make the window wider |
ctrl+w, < | Make the window narrower |
Tabs
command | description |
---|
:tabs | List all tabs, where you can also see which files (buffers) and panes are inside each tab |
:tabnew | Makes a new tab |
:tabclose | Closes the current tab |
:tabn or gt | Go to the next tab |
:tabp or gT | Go to the previous tab |
ngt | Go to the tab in position n (1-based index) |
:tabm n | Move the current tab to the n ‘th position at the top of the screen (0-based index) |
:tabm | Move the current tab to the last position at the top of the screen |
ctrl+w, T | Move the current pane into its own tab |
Linux in vim
command | description |
---|
:!command | Runs a Linux command from inside vim |
Using the mouse
command | description |
---|
hold option | When :set mouse=a is enabled, temporarily treats the mouse as if it wasn’t. (OS X only) |
Plugins
vim
is a masochistic venture without plugins. Here are the ones I strongly recommend:
CtrlP
CtrlP is a vim plugin that lets you “quick find” files, like command+t
in Textmate and Sublime.
command | description |
---|
:CtrlP | Open CtrlP |
ctrl+p | Open CtrlP |
ctrl+v | Open the selected file in a vertical split (CtrlP must be active for this to work) |
ctrl+x | Open the selected file in a horizontal split (CtrlP must be active for this to work) |
:CtrlPClearCache | Clear the CtrlP cache and rebuild; useful if the contents on disk change |
NerdTree
NerdTree is a vim plugin that provides a Windows Explorer-style file list, like the file drawer in Textmate.
command | description |
---|
? | Shows NerdTree help |
r | Refreshes the file list |
C | Set the selected directory as the new root |
I | Show/hide hidden files (toggle) |
m | Select a file in NerdTree and press m to show the nerd tree menu. This menu lets you add, move, delete, or copy files. |
.vimrc
Unfortunately, I cannot share my .vimrc
file as it contains confidential techniques and information.