Vim has several modes. The most important ones are:

To return to normal mode from any other mode, or to cancel a command that is currently being entered, press <ESC>.

The file currently being edited is represented by a buffer, which is contained in a window. One or multiple windows can be arranged within a tab. By default vim starts with a single window in a single tab, and an empty buffer. If file names are provided on the command line, a buffer is created for each file and the first one is shown in the window.

Type :help to open the help file.

Command line mode

Command line mode is invoked by typing : (Ex commands), or / and ? (search commands).

Command Effect
<ENTER> execute command
<TAB> auto complete current command name or parameter
C^d show possible command name or parameter completions
browse backward through command history
browse forward through command history

The * wildcard can be used in command names and parameters. In the context of file operations, ** matches a directory and all its subdirectories (recursively).

The parameter % can be used to refer to the current file, e.g. :w | !bash %.

Multiple commands can be executed at once by concatenating them with a |.

Ex command names can be prefixed by a range. The general syntax is :{from},{to} {command}, where from and to can be one of the following:

Address Meaning
{n} line number n
-{n} n th line before current line
+{n} n th line after current line
. current line
0 before the first line
$ last line in buffer
% the whole buffer
'< begin of visual selection
'> end of visual selection
/{p}/ first line matching pattern p
g/{p}/ all lines matching pattern p
g!/{p}/ all lines not matching pattern p
{n},{m} g/{p}/ all lines between n and n matching pattern p

If from is equal to to, then one of them can be omitted.

Buffer management

In normal mode, the following commands can be issued to open, save and close buffers. All commands can be forced by appending ! to the command name.

Command Effect
:enew open a new, empty buffer
:e {f} open file f
:e re-open the current file
:e# / C^^ open alternate (last edited) file
:find {f} find and open file f (see path option)
:ls show all open buffers
:b {f} switch to buffer of file f
:w save the current buffer to the associated file
:w {f} save the current buffer to file f
:w >>{f} append text to file f
:save {f} clone the current buffer and save the copy to file f
:wa save all buffers
:q close the current window; or vim if it was the last window
:wq save the current buffer, then close it
:qa close all buffers

Window management

Command Effect
:new / C^w n split window horizontally with an empty buffer
:sp / C^w s split window horizontally with same buffer
:sp {f} split window horizontally and edit file f
:sf {f} split window horizontally and find file f
:vnew split window vertically with an empty buffer
C^w v split window vertically with same buffer
:sv {f} split window vertically and edit file f
C^w w go to next window
C^w l/h/k/j go to window to the right/left/above/below
C^w L/H/K/J move window to the right/left/above/below
C^w = align windows evenly across the screen
:clo / C^w c close current window, except if it is the last
:on / C^w o close all other windows

Tab management

Command Effect
:tabe ({f}) open new tab (and edit file f)
:tabf {f} open new tab and find file f
C^w T move current window into a new tab
gt go to next tab
gT go to previous tab
{n}gt go to n th tab
:tabc close current tab
:tabo close all other tabs

File browser

Command Effect
:e. / :Ex open Netrw file browser in current window
:Le {dir} open file browser in new window on the left of the screen

NERDTree is an alternative browser for local files.


The following commands move the cursor around. Most of them can optionally be prefixed with a number, to repeat them multiple times.

Vim differentiates between buffer lines and screen lines. A buffer line that is wrapped occupies two or more screen lines.

A word is defined as a sequence of alphanumerical characters and underscores, or a sequence of any other characters. A WORD is a sequence of any characters except white space. For example, this “text” consists of the four words this, ", text, ", and the two WORDs this and “text”.

Command Effect
l one character to the right
h one character to the left
k / gk one buffer / screen line up
j / gj one buffer / screen line down
0 / g0 first character of buffer / screen line
^ / g^ first non-blank character of buffer / screen line
$ / g$ last character of buffer / screen line
gm middle of screen line
{n}⎮ n th character of the line
- first non-blank character of line above
+ first non-blank character of line below
w / W first character of next word / WORD
b / B first character of previous word / WORD
e / E last character of next word / WORD
ge / gE last character of previous word / WORD
) first character of next sentence
( first character of previous sentence
} line after next paragraph
{ line before previous paragraph
gg first line
{n}G line with number n
G last line
H first line visible in the current window
M middle line visible in the current window
L last line visible in the current window
% match of next parenthesis or bracket on line
f{c} next occurrence of character c on line
F{c} previous occurrence of character c on line
t{c} character before next occurrence of c on line
T{c} character after previous occurrence of c on line
; next match of last f, F, t, or T` search |
, as above (opposite direction)
/{p} next occurrence of pattern p in the buffer
?{p} previous occurrence of pattern p in the buffer
n next match of last / or ? search
N as above (opposite direction)
* next match of the word under or next to the cursor
# as above (opposite direction)

Other navigation commands

The following commands are not considered motions.

A jump is a cursor position change that was caused by a search or substitution command, setting a marker, or motions like G, H, M, L (see :help jump-motions for full list).

Command Effect
:{n} go to line n
C^b scroll one page backward
C^f scroll one page forward
C^u scroll one half page backward
C^d scroll one half page forward
C^y scroll one line backward
C^e scroll one line forward
zz center current line on screen
m{m} place marker m (a-zA-Z) at cursor position
`{m} return to marker m
'{m} as above, but put cursor at first character of line
C^o go backward in jump history
C^i go forward in jump history
`` toggle between last jump and current cursor position
'' as above, but put cursor at first character of line
C^] jump to help topic under the cursor
:ju show jump history
g; go backward in change history
g, go forward in change history
:changes show change history

Manipulating text

{m} indicates that a command needs to be followed by a motion. The command then affects the text area between the current cursor position and the cursor position after performing the motion. If the motion causes a line change, then the command affects whole lines.

For example, c3w (or 3cw) changes the next three words. dj deletes the current line and the line below.

Command Effect
i ⓘ insert text before cursor position
a ⓘ insert text after cursor position
r{c} replace character below cursor with c
R ⓡ overwrite text starting at cursor position
d{m} / :d delete text
dd delete whole line
c{m} ⓘ delete text and enter insert mode
cc ⓘ delete whole line and enter insert mode
o ⓘ create new line below cursor
O ⓘ create new line above cursor
J join current line with next line
:co {a} copy text to address a (see ranges)
:m {a} move text to address a
>{m} / >> indent text
<{m} / << outdent text
={m} auto indent text
~ toggle case of text
:s/{p}/{q}/ substitute first matching pattern p on line with q
:s/{p}/{q}/g same as above, but substitute all matching patterns
:s/{p}/{q}/c same as above, but ask for confirmation
:s//{q}/ substitute last / or ? search pattern with q
:{r}! {e} filter text in range r through external program e
:r {f} paste contents of file f below the current line
:r !{c} paste the output of command c below the current line
:retab! replace whitespace to tabs, requires noexpandtab option
. repeat the last change, including any text insertion
u undo the last change
U undo all changes on the current line
C^r redo the last undone change


Command Equals Effect
x dl delete current character
X dh delete previous character
s cl delete current character and enter insert mode
D d$ delete rest of line
C c$ delete rest of line and enter insert mode
S 0c$ clear whole line and enter insert mode
I ^a insert at the beginning of the line
A $a append to the end of the line

Copying and pasting text

Command Effect
y{m} / :y copy (yank) text into default register
yy / :Y copy whole line
p / :pu paste text from default register after cursor
P / :pu! paste text from default register before cursor
"{r}y{m} / :y {r} copy text into register r (a - z)
"{R}y{m} / :y {R} append text to register r (A - Z)
"{r}p / `:pu {r} | paste text from register r |
:reg show all registers and their content

If a register contains whole lines, its content will be pasted after/before the current line.

The c... and d... / :d commands also copy the affected text into a register before deleting it. The syntax for specifying that register is the same as for the yank command.

Special registers

Key Description
" default (unnamed) register
+ / * system clipboard
% current file name

Visual mode

Command Effect
v start visual mode (select characters)
V start visual mode (select lines)
C^v start visual mode (select rectangular area)
{m} increase or decrease selected area by motion m
o move cursor to opposite side of selected area

The v, V and C^v commands can also change the visual mode type when already in visual mode.

Insert mode

While in insert mode, the following commands can be used:

Command Effect
<Ins> switch to replace mode (and back)
C^→ move cursor to beginning of next word
C^← move cursor to beginning of previous word
<Home> move cursor to beginning of line
<End> move cursor after end of line
C^w delete current word up to cursor
C^u delete entered text (or all, if n/a) on line up to cursor
C^t indent line
C^d outdent line
C^r {r} insert content of register r
C^a insert text that was entered in last insert mode
C^y insert character from same column in line above
C^e insert character from same column in line below
C^o {c} execute normal mode command c and return to insert mode
C^v {k} insert key code of key k (e.g. Enter or Escape key)
C^n keyword completion (from sources as per complete option)
C^x C^n keyword completion (from current buffer)
C^x C^f file name completion of current text
C^x C^o omni completion of current text
C^n (in completion mode) select next suggestion
C^p (in completion mode) select previous suggestion
C^x C^y scroll window one line down
C^x C^e scroll window one line up


Command Effect
q{r} start recording key strokes into register r
q end recording
@{r} play macro stored in register r
@@ replay last macro

An alternative way of creating a macro is to enter the key sequence as text into a buffer and then yanking it into the buffer.

Key mapping


Command Effect
:map {k1} {k2} map key (sequence) k2 to key (sequence) k1
:unmap {k} unmap key sequence

There are several variations of the map command that apply to different modes of Vim, see :help map-modes.

Example: comment out code

Comment out C-like code with the <F7> key (all characters are to be entered literally, except special keys incidated by brackets):

:map #7 I/* [Ctrl+v][Esc]A */[Ctrl+v][Esc]

Alternative way of specifying the keys, and using substitution:

:map <F7> :s/.*/\/* & *\//<CR>:nohls<CR>

Example: align a Markdown table

Consider the following unaligned table:

|Column 1|Column 2|
|Lorem ipsum dolor|sit amet, consetetur|
|sadipscing elitr, sed|diam nonumy eirmod tempor|
|invidunt ut|labore et dolore|
|magna aliquyam|erat, sed diam voluptua.|

The goal is to reformat it so that all the pipe characters are aligned.

Place the following in ~/.vim/ftplugin/markdown.vim:

:xmap <silent> <F2> :s/\|/@\|/g<CR>gv:!column -t -s @<CR>gv:s/\s\s\|/\|/g<CR>\

Then select the whole table in visual mode and press the <F2> key.


  1. :s/\|/@\|/g<CR>: substitute all occurences of | with @|
  2. gv:!column -t -s @<CR>: go back to visual mode with the same selection and filter the text through the external column program, with @ as the column separator
  3. gv:s/\s\s\|/\|/g<CR>: go back to visual mode with the same selection and remove all occurrences of two white space characters that are followed by a pipe (column always replaces the column separator with two spaces)
  4. gv/\%V\|\s*---<CR>: go back to visual mode with the same selection and search within the visual selection (\%V) for the line that separates the header from the body of the table (identified by pipes that are followed by at least three hyphens)
  5. <ESC>:s/\s/-/g<CR>:nohls<CR>: exit visual mode and fill up the spaces within that line with hyphens; finally, disable the highlighted results from that last substitution command


|Column 1             |Column 2                 |
|Lorem ipsum dolor    |sit amet, consetetur     |
|sadipscing elitr, sed|diam nonumy eirmod tempor|
|invidunt ut          |labore et dolore         |
|magna aliquyam       |erat, sed diam voluptua. |

Miscellaneous commands

Command Effect
:normal {c} execute normal mode key sequence on text
:ab {a} {t} define abbreviation a for text t
:! {e} (without a range) execute external program e
:pwd show current working directory
:lcd {d} change working directory to d
:sh open shell (return with exit)
C^g show status line with current cursor position
C^l redraw screen



Command Effect
:set {o} enable option o
:setlocal {o} enable option o for current buffer only
:set no{o} disable option o
:set {o}={v} set o to value v
:set {o}? get value of option o

Important options

Option Effect
hlsearch highlight search results
ignorecase ignore case when searching
incsearch preview search result while typing
mouse enable mouse (resize windows etc.), e.g. set mouse=a
path directories to search, e.g. :set path=.,./**,,

Example: enable JavaScript linting

Add the following to .vim/ftplugin/javascript.vim:

:setlocal makeprg=eslint\ -f\ unix\ %

Running :make will now parse the current JavaScript file with eslint and populate the quickfix list with the results.