The one thing to understand first
Vim has modes. Most editors have one mode where keys type characters. Vim has several, and which mode you’re in changes what every key does.
The most important: Esc always returns you to Normal mode — where keys are commands, not characters.
Quick reference tables
Modes
| Key | Mode | What you can do |
|---|---|---|
| (default) | Normal | Navigate, run commands |
i | Insert | Type text (before cursor) |
a | Insert | Type text (after cursor) |
A | Insert | Type at end of line |
o | Insert | Open new line below, type |
O | Insert | Open new line above, type |
v | Visual | Select characters |
V | Visual Line | Select whole lines |
Ctrl+v | Visual Block | Select a column block |
: | Command | Run Ex commands (:w, :q, etc.) |
/ | Search | Forward search |
? | Search | Backward search |
Exiting Vim
| Command | What it does |
|---|---|
:q | Quit (only if no unsaved changes) |
:q! | Force quit, discard changes |
:w | Save without quitting |
:wq | Save and quit |
:x | Save and quit (same as :wq) |
ZZ | Save and quit (shortcut) |
ZQ | Quit without saving (shortcut) |
Navigation — Normal mode
| Key | Movement |
|---|---|
h j k l | Left · Down · Up · Right |
w | Next word start |
W | Next WORD start (space-delimited) |
b | Previous word start |
e | End of current/next word |
0 | Start of line |
^ | First non-blank character of line |
$ | End of line |
gg | First line of file |
G | Last line of file |
5G or :5 | Go to line 5 |
Ctrl+d | Scroll down half page |
Ctrl+u | Scroll up half page |
Ctrl+f | Scroll down full page |
Ctrl+b | Scroll up full page |
zz | Center cursor on screen |
% | Jump to matching bracket |
{ } | Jump between paragraphs/blank lines |
Editing — Normal mode
| Key | What it does |
|---|---|
x | Delete character under cursor |
X | Delete character before cursor |
dd | Delete (cut) entire line |
5dd | Delete 5 lines |
dw | Delete to end of word |
d$ or D | Delete to end of line |
d0 | Delete to start of line |
yy | Yank (copy) line |
5yy | Yank 5 lines |
yw | Yank word |
p | Paste after cursor |
P | Paste before cursor |
u | Undo |
Ctrl+r | Redo |
r | Replace single character |
R | Enter replace mode (overwrite) |
cc | Change (delete) entire line, enter Insert |
cw | Change to end of word |
c$ or C | Change to end of line |
~ | Toggle case of character |
gu | Lowercase selection (visual) |
gU | Uppercase selection (visual) |
. | Repeat last change |
J | Join current line with next |
Search & replace
| Command | What it does |
|---|---|
/pattern | Search forward |
?pattern | Search backward |
n | Next match |
N | Previous match |
* | Search for word under cursor (forward) |
# | Search for word under cursor (backward) |
:%s/old/new/g | Replace all occurrences in file |
:%s/old/new/gc | Replace all, confirm each |
:5,10s/old/new/g | Replace in lines 5–10 |
:noh | Clear search highlight |
Visual mode
| Key | What it does |
|---|---|
v | Start character selection |
V | Start line selection |
Ctrl+v | Start block/column selection |
o | Move to other end of selection |
y | Yank selection |
d | Delete selection |
c | Delete selection, enter Insert |
> | Indent selection |
< | Unindent selection |
~ | Toggle case |
u | Lowercase |
U | Uppercase |
Split panes & tabs
| Command | What it does |
|---|---|
:sp | Horizontal split (same file) |
:sp file.js | Horizontal split with another file |
:vsp | Vertical split |
:vsp file.js | Vertical split with another file |
Ctrl+w h/j/k/l | Move between panes |
Ctrl+w = | Make all panes equal size |
Ctrl+w _ | Maximize height of current pane |
Ctrl+w | | Maximize width of current pane |
:q | Close current pane |
:tabnew | Open new tab |
:tabnew file.js | Open file in new tab |
gt | Next tab |
gT | Previous tab |
:tabclose | Close current tab |
Marks & jumps
| Command | What it does |
|---|---|
ma | Set mark a at cursor |
`a | Jump to exact position of mark a |
'a | Jump to line of mark a |
Ctrl+o | Jump back (previous position) |
Ctrl+i | Jump forward |
'' | Jump to position before last jump |
Macros
| Command | What it does |
|---|---|
qa | Start recording macro into register a |
q | Stop recording |
@a | Play macro a |
5@a | Play macro a 5 times |
@@ | Repeat last macro |
Detailed sections
The mental model
Think of Vim commands as sentences: verb + motion or verb + text object.
dw— delete wordci"— change inside ” (quotes)ya(— yank around ( (parentheses, including them)vip— visual select inner paragraph
Once you learn the verbs (d, c, y, v) and motions (w, b, e, 0, $) and text objects (iw, aw, i", a(, ip), you can combine them freely.
Text objects — the secret weapon
These work with any verb. i = inner (excluding delimiters), a = around (including delimiters).
| Text object | Selects |
|---|---|
iw | Inner word |
aw | A word (including trailing space) |
i" | Inside double quotes |
a" | Double quotes including the quotes |
i' | Inside single quotes |
i( or ib | Inside parentheses |
a( or ab | Parentheses including them |
i{ or iB | Inside curly braces |
it | Inside HTML/XML tag |
ip | Inner paragraph |
Examples:
ci" → delete inside quotes, start typing
da{ → delete a whole { block } including braces
yip → copy entire paragraph
The dot command — your best friend
. repeats the last change. This is incredibly powerful.
Example: add a semicolon to the end of multiple lines.
A;<Esc> → go to end of line, type ;, escape
j. → go down, repeat
j. → go down, repeat
Search and replace patterns
" Replace all 'foo' with 'bar' in file
:%s/foo/bar/g
" Replace with confirmation
:%s/foo/bar/gc
" Case-insensitive replace
:%s/foo/bar/gi
" Replace only in a visual selection (select first with V, then :)
:'<,'>s/foo/bar/g
" Delete all blank lines
:g/^$/d
" Delete all lines containing 'TODO'
:g/TODO/d
Macros — automate repetitive edits
Example: add quotes around each word on a line.
- Position cursor on first word
qa— start recording into registerabi"<Esc>ea"<Esc>w— add quotes, move to next wordq— stop recording5@a— repeat 5 more times
A minimal .vimrc to get started
" Line numbers
set number
set relativenumber
" Indentation
set tabstop=2
set shiftwidth=2
set expandtab
set autoindent
" Search
set hlsearch
set incsearch
set ignorecase
set smartcase
" UI
set cursorline
set scrolloff=8
set colorcolumn=80
syntax enable
" Mouse support
set mouse=a
" No swap files
set noswapfile
" Better backspace
set backspace=indent,eol,start
Save as ~/.vimrc and restart Vim.
Just need to get out? How to Exit Vim, Vi, and Nano.