Skip to main content

Vim Cheatsheet

A comprehensive quick reference for Vim commands, modes, and workflows. Perfect for developers who need fast access to Vim syntax, navigation, editing, and configuration.

Table of Contents


Prerequisites

Vim Version: This cheatsheet covers Vim 8.0+ and Neovim 0.5+. Some features require specific versions.

Terminal window
# Check Vim version
vim --version
# β†’ VIM - Vi IMproved 8.2
# Check Neovim version
nvim --version
# β†’ NVIM v0.9.0
# Verify minimum version
vim --version | head -1 | grep -oE '[0-9]+\.[0-9]+'

Installation:

  • macOS: brew install vim or brew install neovim
  • Linux: sudo apt install vim (Debian/Ubuntu) or sudo yum install vim (RHEL/CentOS)
  • Windows: Download from vim.org or use choco install vim

Modes

Mode Overview πŸ”„

Vim operates in different modes, each with distinct behaviors:

ModeKeyPurposeCursor Appearance
NormalEscCommand mode, navigationBlock
Inserti, a, oText editingThin vertical bar
VisualvText selectionBlock highlighting
Visual LineVLine selectionFull lines highlighted
Visual BlockCtrl+vColumn selectionColumn highlighting
Command-line:Execute commandsBottom line
" Switch to Normal mode (from any mode)
<Esc> " Escape key
Ctrl+[ " Alternative to Escape
" Enter Insert mode
i " Insert before cursor
a " Insert after cursor
I " Insert at beginning of line
A " Insert at end of line
o " Open new line below
O " Open new line above
" Enter Visual mode
v " Character-wise visual
V " Line-wise visual
Ctrl+v " Block-wise visual
" Enter Command-line mode
: " Execute command
/ " Forward search
? " Backward search

Mode Indicators πŸ“

" Check current mode (in statusline)
:set showmode " Show mode in statusline
:set noshowmode " Hide mode indicator
" Visual feedback
:set cursorline " Highlight current line
:set cursorcolumn " Highlight current column

Basic Navigation

Character & Word Movement 🎯

" Horizontal movement
h " Move left (←)
l " Move right (β†’)
0 " Move to start of line
^ " Move to first non-blank character
$ " Move to end of line
g_ " Move to last non-blank character
" Word movement
w " Next word start (punctuation separated)
W " Next WORD start (whitespace separated)
e " Next word end
E " Next WORD end
b " Previous word start
B " Previous WORD start
ge " Previous word end
gE " Previous WORD end
" Examples
" Text: "hello, world!"
w " β†’ cursor at ","
W " β†’ cursor at "world"
e " β†’ cursor at ","
E " β†’ cursor at "!"

Line Movement πŸ“

" Vertical movement
j " Move down one line
k " Move up one line
gj " Move down one visual line (wrapped)
gk " Move up one visual line (wrapped)
- " Move to first non-blank of previous line
+ " Move to first non-blank of next line
Enter " Move to first non-blank of next line
" Line numbers
gg " Go to first line
G " Go to last line
123G " Go to line 123
:123 " Go to line 123 (command-line)

Screen Movement πŸ–₯️

" Screen scrolling
Ctrl+f " Scroll forward one screen
Ctrl+b " Scroll backward one screen
Ctrl+d " Scroll down half screen
Ctrl+u " Scroll up half screen
Ctrl+e " Scroll down one line
Ctrl+y " Scroll up one line
" Cursor positioning
H " Move to top of screen (High)
M " Move to middle of screen (Middle)
L " Move to bottom of screen (Low)
zz " Center cursor on screen
zt " Move cursor to top of screen
zb " Move cursor to bottom of screen

Paragraph & Section Movement πŸ“„

" Paragraph movement
{ " Previous paragraph (blank line separated)
} " Next paragraph
( " Previous sentence
) " Next sentence
" Section movement
[[ " Previous section (function/class start)
]] " Next section
[] " Previous section end
][ " Next section end

Editing Commands

Insert & Append ✏️

" Insert mode entry
i " Insert before cursor
I " Insert at beginning of line
a " Append after cursor
A " Append at end of line
o " Open new line below
O " Open new line above
gi " Insert at last insert position
" Replace mode
r " Replace single character
R " Replace mode (overwrite)
gr " Virtual replace (preserves tabs)
gR " Virtual replace mode

Delete Commands πŸ—‘οΈ

" Delete characters
x " Delete character under cursor
X " Delete character before cursor
dl " Delete character under cursor (same as x)
dh " Delete character before cursor (same as X)
" Delete words
dw " Delete to start of next word
de " Delete to end of word
dE " Delete to end of WORD
db " Delete to start of word
dB " Delete to start of WORD
daw " Delete a word (including surrounding whitespace)
diw " Delete inner word (word only)
" Delete lines
dd " Delete current line
D " Delete to end of line (same as d$)
d0 " Delete to beginning of line
d^ " Delete to first non-blank
dj " Delete current and next line
dk " Delete current and previous line

Change Commands πŸ”„

" Change (delete + insert)
c " Change (delete + enter insert mode)
cc " Change entire line
C " Change to end of line (same as c$)
ciw " Change inner word
caw " Change a word
ci" " Change inside quotes
ca" " Change around quotes
cit " Change inside tag
cat " Change around tag

Copy & Paste πŸ“‹

" Yank (copy)
y " Yank (copy)
yy " Yank current line
Y " Yank current line (same as yy)
yw " Yank word
y$ " Yank to end of line
y0 " Yank to beginning of line
yiw " Yank inner word
yaw " Yank a word
" Put (paste)
p " Put after cursor/line
P " Put before cursor/line
gp " Put after cursor and move cursor
gP " Put before cursor and move cursor
" Examples
" Copy line 5-10
:5,10yank " Yank lines 5-10
" or
5Gyy10G " Go to line 5, yank, go to line 10

Undo & Redo ↩️

" Undo/Redo
u " Undo last change
Ctrl+r " Redo (undo the undo)
U " Undo all changes on current line
:undo " Undo (command-line)
:redo " Redo (command-line)
" Undo tree (Vim 7.3+)
g+ " Go to newer state
g- " Go to older state
:undolist " Show undo tree
:earlier 5m " Go back 5 minutes
:later 5m " Go forward 5 minutes

Visual Mode

Visual Selection πŸ‘οΈ

" Enter visual mode
v " Character-wise visual mode
V " Line-wise visual mode
Ctrl+v " Block-wise visual mode (column selection)
gv " Reselect last visual selection
" Visual mode commands
d " Delete selection
y " Yank selection
c " Change selection
> " Indent right
< " Indent left
= " Auto-indent
~ " Toggle case
u " Make lowercase
U " Make uppercase
J " Join lines

Visual Block Operations πŸ“¦

" Block selection examples
Ctrl+v " Start block selection
j " Select down
l " Select right
I " Insert at start of block
A " Append at end of block
c " Change block
d " Delete block
" Example: Add comment to multiple lines
Ctrl+v " Enter visual block
jjj " Select 3 lines
I " Insert mode
# " Type comment character
Esc " Apply to all lines
" Example: Change column
Ctrl+v " Enter visual block
jjj " Select lines
lll " Select columns
c " Change
" Type new text
Esc " Apply to all lines

Search & Replace

" Forward search
/pattern " Search forward for pattern
/ " Repeat last search forward
n " Next match
N " Previous match
" Backward search
?pattern " Search backward for pattern
? " Repeat last search backward
n " Previous match (in backward search)
N " Next match (in backward search)
" Search options
/\cpattern " Case-insensitive search
/\Cpattern " Case-sensitive search
/pattern\c " Case-insensitive (at end)
/pattern\> " End of word
/\<pattern " Start of word
/\<pattern\> " Whole word
" Search history
/ " Then use ↑↓ to navigate history
q/ " Open search history window

Replace πŸ”„

" Substitute command
:s/old/new/ " Replace first occurrence in line
:s/old/new/g " Replace all occurrences in line
:s/old/new/gc " Replace with confirmation
:%s/old/new/g " Replace all in file
:%s/old/new/gc " Replace all with confirmation
:5,10s/old/new/g " Replace in lines 5-10
" Using visual selection
" Select text in visual mode, then:
:'<,'>s/old/new/g " Replace in selection
" Special characters
:s/\<old\>/new/g " Whole word match
:s/old/new/gi " Case-insensitive
:s/old/new/gI " Case-sensitive
:s/old/\Unew/g " Uppercase replacement
:s/old/\Lnew/g " Lowercase replacement
:s/old/\Enew/g " End case conversion
" Examples
:%s/foo/bar/g " Replace all 'foo' with 'bar'
:%s/\<the\>/THE/g " Replace whole word 'the' with 'THE'
:%s/.*/\U&/ " Uppercase entire file

Advanced Search Patterns 🎯

" Regular expressions
/^pattern " Line starts with pattern
/pattern$ " Line ends with pattern
/pattern\|other " Pattern OR other
/pattern.*other " Pattern followed by other
/\d\+ " One or more digits
/\w\+ " One or more word characters
/\s\+ " One or more whitespace
" Character classes
/[0-9] " Single digit
/[a-z] " Lowercase letter
/[A-Z] " Uppercase letter
/[^0-9] " Not a digit
/\d " Digit (same as [0-9])
/\w " Word character [a-zA-Z0-9_]
/\s " Whitespace
/\D " Non-digit
/\W " Non-word character
/\S " Non-whitespace
" Quantifiers
/pattern* " Zero or more
/pattern\+ " One or more
/pattern\? " Zero or one
/pattern\{3} " Exactly 3
/pattern\{3,} " 3 or more
/pattern\{3,5} " 3 to 5

File Operations

Opening & Saving Files πŸ’Ύ

" Open file
:e filename " Edit file
:e! " Reload current file (discard changes)
:enew " New empty buffer
:sp filename " Split and edit file
:vsp filename " Vertical split and edit file
" Save file
:w " Save file
:w filename " Save as filename
:w! " Force save (if readonly)
:wa " Save all buffers
:wq " Save and quit
:x " Save and quit (only if modified)
ZZ " Save and quit (normal mode)
ZQ " Quit without saving
" Quit
:q " Quit
:q! " Quit without saving
:qa " Quit all buffers
:wqa " Save all and quit

File Navigation πŸ“

" File explorer
:e . " Open file explorer
:Ex " Explore current directory
:Sex " Split and explore
:Vex " Vertical split and explore
" Netrw navigation (file explorer)
<Enter> " Open file/directory
- " Go up directory
d " Create directory
D " Delete file/directory
R " Rename file/directory
% " Create new file

File Information πŸ“Š

" File info
:f " Show filename and position
:file " Show full filename
:pwd " Print working directory
:cd path " Change directory
:lcd path " Change local directory (buffer only)
" File encoding
:set encoding=utf-8 " Set encoding
:set fileencoding=utf-8 " Set file encoding
:set fileformat=unix " Unix line endings
:set fileformat=dos " Windows line endings

Buffers, Windows & Tabs

Buffers πŸ“š

" Buffer commands
:ls " List buffers
:buffer N " Switch to buffer N
:bn " Next buffer
:bp " Previous buffer
:bfirst " First buffer
:blast " Last buffer
:bdelete N " Delete buffer N
:bd " Delete current buffer
:bw " Wipeout buffer (force delete)
:ball " Open all buffers in windows
" Buffer shortcuts
Ctrl+^ " Switch to alternate buffer
:sbuffer N " Split and switch to buffer

Windows πŸͺŸ

" Split windows
:split " Horizontal split
:sp " Horizontal split (short)
:vsplit " Vertical split
:vs " Vertical split (short)
Ctrl+w s " Split current window
Ctrl+w v " Vertical split current window
" Window navigation
Ctrl+w h " Move to left window
Ctrl+w j " Move to window below
Ctrl+w k " Move to window above
Ctrl+w l " Move to right window
Ctrl+w w " Cycle through windows
Ctrl+w p " Previous window
" Window resizing
Ctrl+w + " Increase height
Ctrl+w - " Decrease height
Ctrl+w > " Increase width
Ctrl+w < " Decrease width
Ctrl+w = " Equalize window sizes
:resize N " Set height to N
:vertical resize N " Set width to N
" Window closing
Ctrl+w c " Close current window
Ctrl+w q " Quit window
Ctrl+w o " Close all other windows (only current)

Tabs πŸ“‘

" Tab commands
:tabnew " New tab
:tabnew file " New tab with file
:tabclose " Close current tab
:tabonly " Close all other tabs
:tabnext " Next tab
:tabprev " Previous tab
:tabfirst " First tab
:tablast " Last tab
:tabmove N " Move tab to position N
" Tab shortcuts
gt " Next tab
gT " Previous tab
Ngt " Go to tab N

Macros

Recording & Playing Macros 🎬

" Record macro
qa " Start recording macro 'a'
" ... perform actions ...
q " Stop recording
" Play macro
@a " Play macro 'a'
@@ " Repeat last macro
N@a " Play macro 'a' N times
" Example: Add semicolon to end of lines
qa " Start recording
A; " Append semicolon
<Esc> " Exit insert mode
j " Move down
q " Stop recording
@a " Play once
10@a " Play 10 times

Macro Management πŸ“

" View macro
:reg a " View contents of macro 'a'
:reg " View all registers
" Edit macro
" 1. Paste macro: "ap (paste macro 'a')
" 2. Edit the text
" 3. Yank back: "ayy (yank line into macro 'a')
" Append to macro
qa " Start recording
@a " Play existing macro
" ... add more actions ...
q " Stop (macro 'a' now includes new actions)

Marks & Jumps

Marks πŸ“

" Set mark
ma " Set mark 'a' at current position
mA " Set global mark 'a' (works across files)
m. " Set mark at last change
m[ " Set mark at start of last change
m] " Set mark at end of last change
" Jump to mark
'a " Jump to mark 'a' (line and column)
`a " Jump to mark 'a' (exact position)
'' " Jump to previous position
`` " Jump to previous position (exact)
`. " Jump to last change
`" " Jump to last edit position
" List marks
:marks " List all marks
:marks a " List mark 'a'

Jumps 🦘

" Jump list
Ctrl+o " Go to older position in jump list
Ctrl+i " Go to newer position (or Tab)
:jumps " List jump positions
" Common jumps
% " Jump to matching bracket/parenthesis
* " Jump to next occurrence of word under cursor
# " Jump to previous occurrence of word
gd " Jump to local definition
gD " Jump to global definition

Text Objects

Text Object Basics 🎯

Text objects allow operations on structured text:

" Text object syntax: operator + text-object
daw " Delete a word
ci" " Change inside quotes
yit " Yank inside tag
" Word objects
iw " Inner word (word only)
aw " A word (word + surrounding whitespace)
iW " Inner WORD
aW " A WORD
" Sentence/Paragraph
is " Inner sentence
as " A sentence
ip " Inner paragraph
ap " A paragraph
" Quotes
i" " Inside double quotes
a" " Around double quotes
i' " Inside single quotes
a' " Around single quotes
i` " Inside backticks
a` " Around backticks
" Brackets
i( " Inside parentheses
a( " Around parentheses (or ib/ab)
i[ " Inside square brackets
a[ " Around square brackets
i{ " Inside curly braces
a{ " Around curly braces (or iB/aB)
i< " Inside angle brackets
a< " Around angle brackets
" Tags (HTML/XML)
it " Inside tag
at " Around tag

Text Object Examples πŸ’‘

" Example: Change text inside quotes
" Text: "Hello world"
ci" " Change inside quotes
" Type: Goodbye
" Result: "Goodbye"
" Example: Delete entire tag
" HTML: <div>content</div>
dat " Delete around tag
" Result: (empty)
" Example: Yank function body
" Code: function test() { return true; }
ci{ " Change inside braces
" Or: di{ to delete, yi{ to yank

Registers

Register Types πŸ“¦

Vim has multiple register types:

" Unnamed register (default)
"" " Last delete/yank/change
" Numbered registers
"0 " Last yank
"1 " Last delete
"2 " Second-to-last delete
"9 " Ninth-to-last delete
" Named registers
"a-"z " User-defined registers
"A-"Z " Append to register (uppercase)
" Special registers
": " Last command-line command
". " Last inserted text
"% " Current filename
"# " Alternate filename
"/ " Last search pattern
"- " Last small delete
"+ " System clipboard (X11 primary)
"* " System clipboard (X11 clipboard)
"= " Expression register
"_ " Black hole register (discard)

Using Registers πŸ’Ύ

" Yank to register
"ayy " Yank line to register 'a'
"ayw " Yank word to register 'a'
"Ayy " Append line to register 'a'
" Put from register
"ap " Put from register 'a'
"aP " Put before from register 'a'
" Delete to register
"add " Delete line to register 'a'
"adw " Delete word to register 'a'
" View registers
:reg " List all registers
:reg a " List register 'a'
" Expression register
"= " Enter expression mode
" Type: 2+2
" Press Enter, then p to paste result (4)

Configuration

Basic Settings βš™οΈ

" Essential settings
:set number " Show line numbers
:set relativenumber " Show relative line numbers
:set nonumber " Hide line numbers
:set number relativenumber " Both absolute and relative
" Indentation
:set autoindent " Auto-indent new lines
:set smartindent " Smart auto-indent
:set cindent " C-style indentation
:set expandtab " Use spaces instead of tabs
:set tabstop=4 " Tab width (display)
:set shiftwidth=4 " Indent width
:set softtabstop=4 " Tab key width
:set noexpandtab " Use tabs
" Search
:set hlsearch " Highlight search results
:set incsearch " Incremental search
:set ignorecase " Case-insensitive search
:set smartcase " Case-sensitive if uppercase
:noh " Clear search highlighting
" Display
:set wrap " Wrap long lines
:set nowrap " Don't wrap lines
:set linebreak " Wrap at word boundaries
:set showcmd " Show command in statusline
:set showmode " Show mode
:set ruler " Show cursor position
:set cursorline " Highlight current line
:set colorcolumn=80 " Highlight column 80
" Behavior
:set hidden " Allow hidden buffers
:set autoread " Auto-reload changed files
:set confirm " Confirm before quitting
:set mouse=a " Enable mouse
:set clipboard=unnamedplus " Use system clipboard

Configuration Files πŸ“

" Vim config location
" Unix/Linux/macOS: ~/.vimrc
" Windows: $HOME\_vimrc or $VIM\_vimrc
" Example .vimrc
set number
set relativenumber
set expandtab
set tabstop=2
set shiftwidth=2
set hlsearch
set incsearch
set ignorecase
set smartcase
set mouse=a
" Source config
:source ~/.vimrc " Reload config
:so ~/.vimrc " Short form

Key Mappings ⌨️

" Map key sequence
:map <key> <command> " Map in normal/visual/operator mode
:nmap <key> <command> " Map in normal mode only
:vmap <key> <command> " Map in visual mode only
:imap <key> <command> " Map in insert mode only
:cmap <key> <command> " Map in command-line mode
" Non-recursive mapping (recommended)
:noremap <key> <command> " Non-recursive normal map
:vnoremap <key> <command> " Non-recursive visual map
:inoremap <key> <command> " Non-recursive insert map
" Leader key
:let mapleader = "," " Set leader to comma
:let maplocalleader = "\\" " Set local leader
" Examples
:map <leader>w :w<CR> " Save with ,w
:nmap <C-s> :w<CR> " Save with Ctrl+s
:inoremap jk <Esc> " Exit insert mode with jk

Plugins

Plugin Managers πŸ”Œ

" vim-plug (recommended)
" Install: curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
" Add to .vimrc:
call plug#begin('~/.vim/plugged')
Plug 'tpope/vim-surround'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
call plug#end()
" Commands
:PlugInstall " Install plugins
:PlugUpdate " Update plugins
:PlugClean " Remove unused plugins
:PlugUpgrade " Upgrade vim-plug itself

Essential Plugins 🌟

" File navigation
" fzf.vim - Fuzzy file finder
" Install: Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
" Install: Plug 'junegunn/fzf.vim'
:Files " Find files
:Buffers " Find buffers
:History " Command history
" Text manipulation
" vim-surround - Surround text with brackets/quotes
" Install: Plug 'tpope/vim-surround'
" Usage: cs"' (change surrounding " to ')
" Usage: ysiw" (surround word with ")
" Git integration
" vim-fugitive - Git wrapper
" Install: Plug 'tpope/vim-fugitive'
:Gstatus " Git status
:Gcommit " Git commit
:Gdiff " Git diff
" Syntax & colors
" Install: Plug 'sheerun/vim-polyglot'
" Auto-detects file types and loads syntax
" Statusline
" Install: Plug 'vim-airline/vim-airline'
" Shows mode, file info, git branch, etc.

Best Practices

Do’s βœ…

" βœ… Use relative line numbers for easier navigation
set relativenumber
" βœ… Use leader key for custom mappings
let mapleader = " "
" βœ… Use non-recursive mappings to avoid conflicts
nnoremap <leader>w :w<CR>
" βœ… Enable hidden buffers for better workflow
set hidden
" βœ… Use system clipboard for copy/paste
set clipboard=unnamedplus
" βœ… Enable incremental search
set incsearch
set hlsearch
" βœ… Use text objects for precise editing
" ci" - change inside quotes
" dat - delete around tag
" βœ… Use marks for navigation
ma " Set mark
'a " Jump to mark
" βœ… Use macros for repetitive tasks
qa " Record macro
@a " Play macro
" βœ… Configure indentation consistently
set expandtab
set tabstop=2
set shiftwidth=2

Don’ts ❌

" ❌ Don't use arrow keys (use hjkl)
" Arrow keys work but break muscle memory
" ❌ Don't use mouse for navigation
" Use keyboard for efficiency
" ❌ Don't use :q then :w (use :wq or :x)
" Inefficient workflow
" ❌ Don't use recursive mappings unless necessary
" Can cause infinite loops
" ❌ Don't disable syntax highlighting
" Helps catch errors
" ❌ Don't use tabs for indentation in most languages
" Use spaces (set expandtab)
" ❌ Don't ignore .vimrc configuration
" Customize for your workflow

Common Pitfalls ⚠️

Warning: Vim is modal - always know which mode you’re in. Press Esc to return to Normal mode if unsure.

Warning: :wq saves and quits, but :q! discards changes. Double-check before quitting.

Warning: Macros are stored in registers. Recording a new macro with the same name overwrites the old one.

Warning: Visual mode selections are lost when switching modes. Use marks or registers to preserve positions.


Common Workflows

Code Editing Workflow πŸ’»

" 1. Open file
vim file.js
" 2. Navigate to function
/function " Search for function
n " Next match
" 3. Edit function
ci{ " Change inside braces
" Type new code
<Esc> " Exit insert mode
" 4. Save and continue
:w " Save
:bn " Next buffer

Refactoring Workflow πŸ”§

" 1. Find and replace variable name
:%s/oldVar/newVar/gc " Replace with confirmation
" 2. Use visual block to edit multiple lines
Ctrl+v " Visual block
jjj " Select lines
I " Insert mode
" Type prefix
<Esc> " Apply to all
" 3. Use macro for repetitive changes
qa " Record macro
" Perform change
j " Next line
q " Stop
@a " Play macro
10@a " Play 10 times

Multi-file Editing Workflow πŸ“š

" 1. Open multiple files
vim file1.js file2.js file3.js
" 2. Navigate buffers
:ls " List buffers
:bn " Next buffer
:bp " Previous buffer
Ctrl+^ " Alternate buffer
" 3. Split windows
:sp file2.js " Horizontal split
Ctrl+w w " Switch windows
" 4. Use tabs for different projects
:tabnew " New tab
gt " Next tab

Search & Replace Workflow πŸ”

" 1. Search for pattern
/pattern " Search forward
?pattern " Search backward
" 2. Navigate matches
n " Next match
N " Previous match
" 3. Replace in selection
" Select text in visual mode
:'<,'>s/old/new/g " Replace in selection
" 4. Replace in entire file
:%s/old/new/gc " Replace all with confirmation