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
- Modes
- Basic Navigation
- Editing Commands
- Visual Mode
- Search & Replace
- File Operations
- Buffers, Windows & Tabs
- Macros
- Marks & Jumps
- Text Objects
- Registers
- Configuration
- Plugins
- Best Practices
- Common Workflows
Prerequisites
Vim Version: This cheatsheet covers Vim 8.0+ and Neovim 0.5+. Some features require specific versions.
# Check Vim versionvim --version# β VIM - Vi IMproved 8.2
# Check Neovim versionnvim --version# β NVIM v0.9.0
# Verify minimum versionvim --version | head -1 | grep -oE '[0-9]+\.[0-9]+'Installation:
- macOS:
brew install vimorbrew install neovim - Linux:
sudo apt install vim(Debian/Ubuntu) orsudo 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:
| Mode | Key | Purpose | Cursor Appearance |
|---|---|---|---|
| Normal | Esc | Command mode, navigation | Block |
| Insert | i, a, o | Text editing | Thin vertical bar |
| Visual | v | Text selection | Block highlighting |
| Visual Line | V | Line selection | Full lines highlighted |
| Visual Block | Ctrl+v | Column selection | Column highlighting |
| Command-line | : | Execute commands | Bottom line |
" Switch to Normal mode (from any mode)<Esc> " Escape keyCtrl+[ " Alternative to Escape
" Enter Insert modei " Insert before cursora " Insert after cursorI " Insert at beginning of lineA " Insert at end of lineo " Open new line belowO " Open new line above
" Enter Visual modev " Character-wise visualV " Line-wise visualCtrl+v " Block-wise visual
" Enter Command-line mode: " Execute command/ " Forward search? " Backward searchMode 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 columnBasic Navigation
Character & Word Movement π―
" Horizontal movementh " Move left (β)l " Move right (β)0 " Move to start of line^ " Move to first non-blank character$ " Move to end of lineg_ " Move to last non-blank character
" Word movementw " Next word start (punctuation separated)W " Next WORD start (whitespace separated)e " Next word endE " Next WORD endb " Previous word startB " Previous WORD startge " Previous word endgE " Previous WORD end
" Examples" Text: "hello, world!"w " β cursor at ","W " β cursor at "world"e " β cursor at ","E " β cursor at "!"Line Movement π
" Vertical movementj " Move down one linek " Move up one linegj " 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 lineEnter " Move to first non-blank of next line
" Line numbersgg " Go to first lineG " Go to last line123G " Go to line 123:123 " Go to line 123 (command-line)Screen Movement π₯οΈ
" Screen scrollingCtrl+f " Scroll forward one screenCtrl+b " Scroll backward one screenCtrl+d " Scroll down half screenCtrl+u " Scroll up half screenCtrl+e " Scroll down one lineCtrl+y " Scroll up one line
" Cursor positioningH " Move to top of screen (High)M " Move to middle of screen (Middle)L " Move to bottom of screen (Low)zz " Center cursor on screenzt " Move cursor to top of screenzb " Move cursor to bottom of screenParagraph & 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 endEditing Commands
Insert & Append βοΈ
" Insert mode entryi " Insert before cursorI " Insert at beginning of linea " Append after cursorA " Append at end of lineo " Open new line belowO " Open new line abovegi " Insert at last insert position
" Replace moder " Replace single characterR " Replace mode (overwrite)gr " Virtual replace (preserves tabs)gR " Virtual replace modeDelete Commands ποΈ
" Delete charactersx " Delete character under cursorX " Delete character before cursordl " Delete character under cursor (same as x)dh " Delete character before cursor (same as X)
" Delete wordsdw " Delete to start of next wordde " Delete to end of worddE " Delete to end of WORDdb " Delete to start of worddB " Delete to start of WORDdaw " Delete a word (including surrounding whitespace)diw " Delete inner word (word only)
" Delete linesdd " Delete current lineD " Delete to end of line (same as d$)d0 " Delete to beginning of lined^ " Delete to first non-blankdj " Delete current and next linedk " Delete current and previous lineChange Commands π
" Change (delete + insert)c " Change (delete + enter insert mode)cc " Change entire lineC " Change to end of line (same as c$)ciw " Change inner wordcaw " Change a wordci" " Change inside quotesca" " Change around quotescit " Change inside tagcat " Change around tagCopy & Paste π
" Yank (copy)y " Yank (copy)yy " Yank current lineY " Yank current line (same as yy)yw " Yank wordy$ " Yank to end of liney0 " Yank to beginning of lineyiw " Yank inner wordyaw " Yank a word
" Put (paste)p " Put after cursor/lineP " Put before cursor/linegp " Put after cursor and move cursorgP " Put before cursor and move cursor
" Examples" Copy line 5-10:5,10yank " Yank lines 5-10" or5Gyy10G " Go to line 5, yank, go to line 10Undo & Redo β©οΈ
" Undo/Redou " Undo last changeCtrl+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 stateg- " Go to older state:undolist " Show undo tree:earlier 5m " Go back 5 minutes:later 5m " Go forward 5 minutesVisual Mode
Visual Selection ποΈ
" Enter visual modev " Character-wise visual modeV " Line-wise visual modeCtrl+v " Block-wise visual mode (column selection)gv " Reselect last visual selection
" Visual mode commandsd " Delete selectiony " Yank selectionc " Change selection> " Indent right< " Indent left= " Auto-indent~ " Toggle caseu " Make lowercaseU " Make uppercaseJ " Join linesVisual Block Operations π¦
" Block selection examplesCtrl+v " Start block selectionj " Select downl " Select rightI " Insert at start of blockA " Append at end of blockc " Change blockd " Delete block
" Example: Add comment to multiple linesCtrl+v " Enter visual blockjjj " Select 3 linesI " Insert mode# " Type comment characterEsc " Apply to all lines
" Example: Change columnCtrl+v " Enter visual blockjjj " Select lineslll " Select columnsc " Change" Type new textEsc " Apply to all linesSearch & Replace
Search π
" Forward search/pattern " Search forward for pattern/ " Repeat last search forwardn " Next matchN " Previous match
" Backward search?pattern " Search backward for pattern? " Repeat last search backwardn " 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 historyq/ " Open search history windowReplace π
" 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 fileAdvanced 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 5File 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 quitFile 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 directoryd " Create directoryD " Delete file/directoryR " Rename file/directory% " Create new fileFile 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 endingsBuffers, 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 shortcutsCtrl+^ " Switch to alternate buffer:sbuffer N " Split and switch to bufferWindows πͺ
" Split windows:split " Horizontal split:sp " Horizontal split (short):vsplit " Vertical split:vs " Vertical split (short)Ctrl+w s " Split current windowCtrl+w v " Vertical split current window
" Window navigationCtrl+w h " Move to left windowCtrl+w j " Move to window belowCtrl+w k " Move to window aboveCtrl+w l " Move to right windowCtrl+w w " Cycle through windowsCtrl+w p " Previous window
" Window resizingCtrl+w + " Increase heightCtrl+w - " Decrease heightCtrl+w > " Increase widthCtrl+w < " Decrease widthCtrl+w = " Equalize window sizes:resize N " Set height to N:vertical resize N " Set width to N
" Window closingCtrl+w c " Close current windowCtrl+w q " Quit windowCtrl+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 shortcutsgt " Next tabgT " Previous tabNgt " Go to tab NMacros
Recording & Playing Macros π¬
" Record macroqa " Start recording macro 'a'" ... perform actions ...q " Stop recording
" Play macro@a " Play macro 'a'@@ " Repeat last macroN@a " Play macro 'a' N times
" Example: Add semicolon to end of linesqa " Start recordingA; " Append semicolon<Esc> " Exit insert modej " Move downq " Stop recording@a " Play once10@a " Play 10 timesMacro 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 macroqa " Start recording@a " Play existing macro" ... add more actions ...q " Stop (macro 'a' now includes new actions)Marks & Jumps
Marks π
" Set markma " Set mark 'a' at current positionmA " Set global mark 'a' (works across files)m. " Set mark at last changem[ " Set mark at start of last changem] " 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 listCtrl+o " Go to older position in jump listCtrl+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 wordgd " Jump to local definitiongD " Jump to global definitionText Objects
Text Object Basics π―
Text objects allow operations on structured text:
" Text object syntax: operator + text-objectdaw " Delete a wordci" " Change inside quotesyit " Yank inside tag
" Word objectsiw " Inner word (word only)aw " A word (word + surrounding whitespace)iW " Inner WORDaW " A WORD
" Sentence/Paragraphis " Inner sentenceas " A sentenceip " Inner paragraphap " A paragraph
" Quotesi" " Inside double quotesa" " Around double quotesi' " Inside single quotesa' " Around single quotesi` " Inside backticksa` " Around backticks
" Bracketsi( " Inside parenthesesa( " Around parentheses (or ib/ab)i[ " Inside square bracketsa[ " Around square bracketsi{ " Inside curly bracesa{ " Around curly braces (or iB/aB)i< " Inside angle bracketsa< " Around angle brackets
" Tags (HTML/XML)it " Inside tagat " Around tagText 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 yankRegisters
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 clipboardConfiguration Files π
" Vim config location" Unix/Linux/macOS: ~/.vimrc" Windows: $HOME\_vimrc or $VIM\_vimrc
" Example .vimrcset numberset relativenumberset expandtabset tabstop=2set shiftwidth=2set hlsearchset incsearchset ignorecaseset smartcaseset mouse=a
" Source config:source ~/.vimrc " Reload config:so ~/.vimrc " Short formKey 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 jkPlugins
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 itselfEssential 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 navigationset relativenumber
" β
Use leader key for custom mappingslet mapleader = " "
" β
Use non-recursive mappings to avoid conflictsnnoremap <leader>w :w<CR>
" β
Enable hidden buffers for better workflowset hidden
" β
Use system clipboard for copy/pasteset clipboard=unnamedplus
" β
Enable incremental searchset incsearchset hlsearch
" β
Use text objects for precise editing" ci" - change inside quotes" dat - delete around tag
" β
Use marks for navigationma " Set mark'a " Jump to mark
" β
Use macros for repetitive tasksqa " Record macro@a " Play macro
" β
Configure indentation consistentlyset expandtabset tabstop=2set shiftwidth=2Donβ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 workflowCommon Pitfalls β οΈ
Warning: Vim is modal - always know which mode youβre in. Press
Escto return to Normal mode if unsure.
Warning:
:wqsaves 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 filevim file.js
" 2. Navigate to function/function " Search for functionn " Next match
" 3. Edit functionci{ " Change inside braces" Type new code<Esc> " Exit insert mode
" 4. Save and continue:w " Save:bn " Next bufferRefactoring Workflow π§
" 1. Find and replace variable name:%s/oldVar/newVar/gc " Replace with confirmation
" 2. Use visual block to edit multiple linesCtrl+v " Visual blockjjj " Select linesI " Insert mode" Type prefix<Esc> " Apply to all
" 3. Use macro for repetitive changesqa " Record macro" Perform changej " Next lineq " Stop@a " Play macro10@a " Play 10 timesMulti-file Editing Workflow π
" 1. Open multiple filesvim file1.js file2.js file3.js
" 2. Navigate buffers:ls " List buffers:bn " Next buffer:bp " Previous bufferCtrl+^ " Alternate buffer
" 3. Split windows:sp file2.js " Horizontal splitCtrl+w w " Switch windows
" 4. Use tabs for different projects:tabnew " New tabgt " Next tabSearch & Replace Workflow π
" 1. Search for pattern/pattern " Search forward?pattern " Search backward
" 2. Navigate matchesn " Next matchN " 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