Getting Started
Modes & Basic Movement
Vim is modal — different modes serve different purposes. Esc returns to Normal mode from any other mode. The hjkl keys keep your hands on the home row. w/b move by word, 0/$ move to line boundaries, gg/G jump to file start/end, :N jumps to line N.
# Vim Modes
# Normal mode (Esc) - default, for navigation
# Insert mode (i) - for typing text
# Visual mode (v) - for selecting text
# Command mode (:) - for Ex commands
# Basic movement (Normal mode)
h # left
j # down
k # up
l # right
w # next word start
b # previous word start
0 # beginning of line
$ # end of line
gg # first line
G # last line
:42 # go to line 42Exiting & Saving
ZZ and ZQ are the fastest ways to exit — they don't require reaching for the colon. :x only writes if the file has changed (preserves mtime), unlike :wq which always writes. :w! overrides read-only flags if filesystem permissions allow. Use :qa! to bail out of multiple modified buffers.
:w # write (save) file
:w! # force write (override read-only)
:q # quit
:q! # force quit (discard changes)
:wq # write and quit
:x # write only if changed, then quit
ZZ # same as :x (write if changed, quit)
ZQ # quit without saving (like :q!)
:w newfile.txt # save as new file
:sav newfile.txt # save as new file and switch to it
:wa # write all buffers
:xa # write all changed buffers and exit
:qa! # force quit all (discard everything)Help System
Vim's help is comprehensive and hyperlinked. Ctrl-] follows a tag (link) and Ctrl-T pops back. Help notation: i_CTRL-N means Ctrl-N in insert mode, 'number' (with quotes) means an option. :helpgrep searches all help files at once — use :cn/:cp to navigate matches. K invokes man for the keyword under the cursor (configurable via 'keywordprg').
:help # main help
:help subject # help on subject (e.g. :help insert)
:help i_CTRL-N # help on Ctrl-N in insert mode
:help 'number' # help on the 'number' option (quotes)
:helpgrep pattern # search all help files for pattern
:cn / :cp # next/prev helpgrep match
K # man page for word under cursor (Normal mode)
Ctrl-] # jump to tag under cursor (follow link)
Ctrl-T # jump back from tag (pop tag stack)
:helptags ~/.vim/doc # regenerate help tags for a doc directoryWord & Character Movement
Lowercase motions (w/b/e) treat punctuation as word separators — useful for code. Uppercase motions (W/B/E) only treat whitespace as separators — useful for prose. e/E move to the end of the next word; ge/gE move to the end of the previous word (rarely used but handy).
# Word motions (punctuation-aware)
w # next word start
b # previous word start
e # end of next word
ge # end of previous word
# WORD motions (whitespace-only delimiters, uppercase)
W # next WORD start
B # previous WORD start
E # end of next WORD
gE # end of previous WORD
# Word boundaries:
# word: sequence of word-characters OR sequence of punctuation
# WORD: anything separated by whitespace
# Examples (cursor on 'a' in "foo.bar baz"):
# w -> 'bar' (punctuation splits words)
# W -> 'baz' (only whitespace splits WORDS)Line Movement
0 and $ go to absolute line start/end (including whitespace). ^ and g_ skip leading/trailing whitespace — usually what you want. When 'wrap' is on, g0/g$ operate on screen lines while 0/$ operate on logical lines. | jumps to a specific column number.
0 # first column (absolute start)
^ # first non-blank character
$ # end of line (last character)
g_ # last non-blank character
g0 # start of screen line (with wrap)
g$ # end of screen line (with wrap)
gm # middle of screen line
gM # middle of text line
| # column N (e.g. 10| = column 10)
+ # first non-blank of next line
- # first non-blank of previous line
_ # first non-blank of current line [count down]File & Screen Movement
H/M/L jump within the visible screen. Ctrl-d/u scroll half a page (less disorienting than full-page Ctrl-f/b). zz/zt/zb scroll the current line to the middle/top/bottom of the screen without moving the cursor — extremely useful for keeping context while editing. N% jumps to a percentage of the file.
gg # go to first line
G # go to last line
Ngg / NG # go to line N (e.g. 50gg or 50G)
:N # go to line N (Ex command)
H # top of screen (High)
M # middle of screen
L # bottom of screen (Low)
N% # jump to N% of the file
Ctrl-f # scroll forward (full page)
Ctrl-b # scroll backward (full page)
Ctrl-d # scroll down (half page)
Ctrl-u # scroll up (half page)
zz # scroll current line to middle
zt # scroll current line to top
zb # scroll current line to bottomInserting Text
Basic Insert (i, I)
i/I insert before the cursor / at line start. a/A insert after the cursor / at line end. gi returns to the last insert position (mark '^) — handy when you Esc to do something then want to keep typing. gI goes to the absolute column 1, ignoring leading whitespace.
i # insert before cursor
I # insert at first non-blank (same as ^i)
gi # insert at last insert position (also sets mark)
gI # insert at column 1 (same as 0i)
a # insert after cursor
A # insert at end of line (same as $a)
# Examples:
# foo|bar + i -> foo|bar (cursor stays, type before)
# foo|bar + I -> |foobar (cursor at first non-blank)
# foo|bar + A -> foobar| (cursor at end)
# gi returns to where you last left insert mode —
# very useful after escaping to run a Normal-mode command.Open New Lines (o, O)
o and O open a new line below/above the cursor and enter insert mode. They're the fastest way to add a line — no need to position the cursor at line end. Indentation is auto-copied from the surrounding lines (controlled by 'autoindent').
o # open new line BELOW cursor, enter insert
O # open new line ABOVE cursor, enter insert
# Before (cursor on middle line):
# line one
# li|ne two
# line three
# After 'o':
# line one
# line two
# | <- new blank line, insert mode
# line three
# After 'O':
# line one
# | <- new blank line, insert mode
# line two
# line threeChange Commands (c, C, s, S)
c{motion} deletes the motion target and enters insert mode — the most flexible edit command. C is c$ (change to end of line), S is cc (change whole line). s deletes one character and enters insert; combine with counts like 3s. ciw/caw use text objects (see dedicated section).
cw / ce # change to end of word
cb # change backward to word start
c$ / C # change to end of line
cc / S # change entire line
c0 # change to beginning of line
c^ # change to first non-blank
ct, # change up to (but not including) next ','
cfx # change up to and including next 'x'
ciw # change inner word (no surrounding whitespace)
caw # change a word (with surrounding whitespace)
cap # change around paragraph
s # substitute: delete char under cursor, insert
S # substitute: delete entire line, insert (like cc)Replace Mode (r, R, gr)
r replaces a single character and returns to Normal mode immediately (no mode change). R enters Replace mode where typing overwrites characters — Backspace restores them, unlike Insert mode which just deletes. Use gr/gR (virtual replace) when working with tabs — it preserves tab alignment instead of shifting text.
r{x} # replace single char under cursor with x
gr{x} # virtual replace (doesn't shift tabs)
R # enter Replace mode (overwrite until Esc)
gR # virtual Replace mode (tabs stay aligned)
3r{x} # replace 3 chars with x (single char only)
# In Replace mode, typing overwrites existing text
# but Backspace restores the original characters.
# Tabs are preserved with virtual replace (gr/gR).
# Examples:
# abc|def + rx -> abc|xef (cursor advances)
# abc|def + R -> enter Replace mode
# type 'XYZ' -> abcXYZ|f
# Backspace -> abcXY|def (original restored)Special Inserts
:r !cmd inserts shell command output into the buffer — great for pasting command output, dates, file lists. In insert mode, Ctrl-r followed by a register name inserts that register; Ctrl-r = evaluates a Vimscript expression and inserts the result. Ctrl-k inserts a digraph (special character) by typing two ASCII chars.