Introduction
VIM is intimidating at first. Once basic motions click, you edit faster than any mouse user.
This guide covers the shortcuts that matter most.
Pro Tip: Donβt try to memorize everything at once. Pick 3-5 commands from each section and practice them daily. Muscle memory will develop naturally over time.
VIM Modes Overview
VIM has four modes:
| Mode | Description | How to Enter |
|---|---|---|
| Normal | Navigate and execute commands | Esc |
| Insert | Type text like a regular editor | i, a, o |
| Visual | Select text | v, V, Ctrl+v |
| Command | Execute Ex commands | : |
Golden Rule: Always return to Normal mode after editing. Hit Esc frequently!
Basic Movement (Normal Mode)
Character-Level Movement
| Command | Action | Example |
|---|---|---|
h | Move left | Move 1 character left |
l | Move right | Move 1 character right |
j | Move down | Move 1 line down |
k | Move up | Move 1 line up |
j as a down arrow (β) and k as an up arrow (β). Fast Movement Within Lines
| Command | Action | Use Case |
|---|---|---|
0 | Start of line (column 0) | Jump to very beginning |
^ | First non-blank character | Skip indentation |
$ | End of line | Jump to line end |
g_ | Last non-blank character | Skip trailing spaces |
Example:
const message = "Hello World";
0β column 0 (before spaces)^β βcβ in βconstβ$β after β;β and spacesg_β the β;β
Word-Level Movement
| Command | Action | Example |
|---|---|---|
w | Next word (forward) | const β message |
b | Previous word (backward) | message β const |
e | End of word | Move to last char of word |
W | Next WORD (space-delimited) | Skip punctuation |
B | Previous WORD | Backward, skip punctuation |
w vs W:
const user.name = "John-Doe";
w:user,.,name,=,",John,-,Doeare separate wordsW:user.name,=,"John-Doe"are WORDS (space-delimited)
Line-Level Movement
| Command | Action | Tip |
|---|---|---|
gg | First line of file | Jump to top |
G | Last line of file | Jump to bottom |
42G or :42 | Line 42 | Go to specific line |
50% | 50% of file | Jump to middle |
H | Top of screen (High) | Visible area only |
M | Middle of screen | Visible area only |
L | Bottom of screen (Low) | Visible area only |
Search-Based Movement
| Command | Action | Example |
|---|---|---|
f{char} | Find forward to char | fa β find next βaβ |
F{char} | Find backward to char | Fa β find previous βaβ |
t{char} | Till forward (before char) | ta β move before βaβ |
T{char} | Till backward (after char) | Ta β move after βaβ |
; | Repeat last f/t/F/T | Find next occurrence |
, | Reverse last f/t/F/T | Find previous occurrence |
Example:
const userName = 'JohnDoe'
Cursor on βcβ, type fe β jumps to βeβ in βuserNameβ.
Type ; β jumps to βeβ in ββJohnDoeββ.
Search with / and ?
| Command | Action | Notes |
|---|---|---|
/pattern | Search forward | Type pattern, press Enter |
?pattern | Search backward | Reverse search |
n | Next match | Same direction |
N | Previous match | Opposite direction |
* | Search word under cursor (forward) | Quick search |
# | Search word under cursor (backward) | Quick search |
Example Workflow:
- Cursor on
userName *β highlights all occurrencesnβ next occurrenceNβ previous occurrence
Fast Editing (Normal Mode)
Insert Mode Shortcuts
| Command | Action | Cursor Position |
|---|---|---|
i | Insert before cursor | Current position |
I | Insert at line start | First non-blank char |
a | Append after cursor | One char right |
A | Append at line end | End of line |
o | Open line below | New line below |
O | Open line above | New line above |
s | Substitute char | Delete char + insert |
S | Substitute line | Delete line + insert |
Use A instead of $a. Use I instead of ^i.
Deletion Commands
| Command | Action | Memory Aid |
|---|---|---|
x | Delete character | Cut char under cursor |
X | Delete char before | Backspace in normal mode |
dd | Delete line | Cut entire line |
dw | Delete word | From cursor to word end |
db | Delete word backward | To word start |
d$ or D | Delete to line end | From cursor to EOL |
d0 | Delete to line start | From cursor to start |
dG | Delete to file end | From cursor to EOF |
dgg | Delete to file start | From cursor to top |
Change Commands (Delete + Insert)
| Command | Action | Equivalent |
|---|---|---|
cw | Change word | dwi |
c$ or C | Change to line end | d$i |
cc or S | Change entire line | ddi |
ciw | Change inner word | Delete word under cursor |
ci" | Change inside quotes | Replace text in ββ¦β |
ci{ | Change inside braces | Replace text in {...} |
cit | Change inside tag | Replace HTML tag content |
Example:
const message = 'Hello World'
- Cursor on any char in βHello Worldβ
ci"β deletes βHello Worldβ, enters insert mode- Type new text β
"New Message"
Copy (Yank) and Paste
| Command | Action | Notes |
|---|---|---|
yy or Y | Yank (copy) line | Copy entire line |
yw | Yank word | From cursor to word end |
y$ | Yank to line end | From cursor to EOL |
ygg | Yank to file start | From cursor to top |
yG | Yank to file end | From cursor to bottom |
p | Paste after cursor | Paste below line |
P | Paste before cursor | Paste above line |
System Clipboard:
"+yβ Copy to system clipboard"+pβ Paste from system clipboard
Undo and Redo
| Command | Action |
|---|---|
u | Undo last change |
Ctrl+r | Redo (undo the undo) |
U | Undo all changes on line |
Repeat Last Command
| Command | Action | Use Case |
|---|---|---|
. | Repeat last change | Super powerful! |
Example:
dwβ delete word- Move to another word
.β deletes that word too
Works with any change: dd, ciw, x, etc.
Visual Mode Shortcuts
Entering Visual Mode
| Command | Mode | Selection Type |
|---|---|---|
v | Visual | Character-wise |
V | Visual Line | Line-wise |
Ctrl+v | Visual Block | Column-wise (rectangle) |
Operating on Visual Selections
After selecting:
| Command | Action |
|---|---|
d | Delete selection |
c | Change selection |
y | Yank (copy) selection |
> | Indent right |
< | Indent left |
= | Auto-indent |
u | Lowercase |
U | Uppercase |
~ | Toggle case |
Example - Comment Multiple Lines:
Ctrl+vβ enter visual block modejjjβ select 4 linesIβ insert at start of block#β type comment characterEscβ apply to all lines
Text Objects (Game Changer!)
Operate on logical chunks of text instead of character-by-character.
Syntax
| Pattern | Meaning |
|---|---|
i | Inner (excludes delimiters) |
a | Around (includes delimiters) |
Common Text Objects
| Object | Description | Example |
|---|---|---|
iw | Inner word | Word under cursor |
aw | A word (with space) | Word + trailing space |
is | Inner sentence | Current sentence |
as | A sentence | Sentence + space |
ip | Inner paragraph | Paragraph (blank-delimited) |
ap | A paragraph | Paragraph + blank line |
i" | Inner quotes | Text inside ββ¦β |
a" | Around quotes | Text + ββ¦β |
i( or ib | Inner parentheses | Text inside (β¦) |
a( or ab | Around parentheses | Text + (β¦) |
i{ or iB | Inner braces | Text inside {...} |
a{ or aB | Around braces | Text + {...} |
it | Inner tag | Inside HTML tag |
at | Around tag | HTML tag + content |
Powerful Combinations
| Command | Action | Example |
|---|---|---|
ciw | Change inner word | Replace word |
daw | Delete a word | Delete word + space |
di" | Delete inside quotes | Clear βtextβ |
da" | Delete around quotes | Remove βtextβ entirely |
ci{ | Change inside braces | Replace {...} content |
dit | Delete inside tag | Clear <p>text</p> |
vit | Select inside tag | Select tag content |
yip | Yank inner paragraph | Copy paragraph |
Real-World Example:
const user = {
name: 'John Doe',
email: 'john@example.com',
}
- Cursor anywhere inside
{...} ci{β deletes content, stays in{...}- Type new object content
Search and Replace
Basic Find/Replace
| Command | Action | Scope |
|---|---|---|
:s/old/new/ | Replace first on line | Current line |
:s/old/new/g | Replace all on line | Current line |
:%s/old/new/g | Replace all in file | Entire file |
:%s/old/new/gc | Replace with confirmation | Interactive |
:5,10s/old/new/g | Replace in lines 5-10 | Range |
Visual Selection Replace
- Select text with
vorV - Type
:(shows:'<,'>) - Type
s/old/new/g - Press Enter
Case-Insensitive Search
| Command | Action |
|---|---|
/pattern\c | Case-insensitive search |
/pattern\C | Case-sensitive search |
:set ic | Set ignore case globally |
:set noic | Turn off ignore case |
Numbers as Multipliers
Prefix any command with a number to repeat it.
| Command | Action |
|---|---|
5j | Move down 5 lines |
3w | Move forward 3 words |
10dd | Delete 10 lines |
2yy | Yank 2 lines |
4x | Delete 4 characters |
80i-[Esc] | Insert 80 dashes |
3p | Paste 3 times |
5>> | Indent 5 lines right |
Practical Example:
# Need to insert 50 equals signs
50i=[Esc]
Result: ==================================================
Marks and Jumps
Marks (Bookmarks)
| Command | Action | Scope |
|---|---|---|
ma | Set mark βaβ | Local to file |
mA | Set mark βAβ | Global (across files) |
`a | Jump to mark βaβ | Exact position |
'a | Jump to line of mark βaβ | First non-blank |
:marks | List all marks | Show marks |
Jump List
| Command | Action |
|---|---|
Ctrl+o | Jump to older position |
Ctrl+i | Jump to newer position |
:jumps | Show jump list |
Change List
| Command | Action |
|---|---|
g; | Jump to older change position |
g, | Jump to newer change position |
:changes | Show change list |
Window and Buffer Management
Split Windows
| Command | Action |
|---|---|
:split or :sp | Horizontal split |
:vsplit or :vsp | Vertical split |
Ctrl+w s | Horizontal split |
Ctrl+w v | Vertical split |
Ctrl+w w | Switch to next window |
Ctrl+w h/j/k/l | Navigate windows |
Ctrl+w q | Close current window |
Ctrl+w = | Equalize window sizes |
Buffer Navigation
| Command | Action |
|---|---|
:ls or :buffers | List all buffers |
:b 2 | Switch to buffer 2 |
:bn | Next buffer |
:bp | Previous buffer |
:bd | Delete (close) buffer |
:b filename | Switch to buffer by name |
Advanced Efficiency Tips
Macros (Record and Replay)
| Command | Action |
|---|---|
qa | Start recording to register βaβ |
q | Stop recording |
@a | Play macro from register βaβ |
@@ | Repeat last macro |
5@a | Play macro βaβ 5 times |
Example - Add semicolons to multiple lines:
qaβ start recording to register βaβA;[Esc]β append semicolonjβ move downqβ stop recording10@aβ repeat 10 times
Global Commands
| Command | Action | Example |
|---|---|---|
:g/pattern/d | Delete lines matching pattern | Remove all console.log |
:v/pattern/d | Delete lines not matching pattern | Keep only pattern |
:g/TODO/p | Print lines matching pattern | Find all TODOs |
:g/^$/d | Delete empty lines | Clean up |
Example:
:g/console.log/d # Delete all lines with console.log
:v/^import/d # Delete all lines except imports
:g/TODO:/norm A !!! # Append !!! to all TODO lines
Sorting and Filtering
| Command | Action |
|---|---|
:sort | Sort lines alphabetically |
:sort! | Sort in reverse |
:sort u | Sort and remove duplicates |
:%!sort | Sort using external command |
Auto-Completion (Insert Mode)
| Command | Completion Type |
|---|---|
Ctrl+n | Next word completion |
Ctrl+p | Previous word completion |
Ctrl+x Ctrl+f | File name completion |
Ctrl+x Ctrl+l | Line completion |
Quick Reference Cheat Sheet
Movement Quick Reference
Character: h β | j β | k β | l β
Line: 0 start | ^ first-char | $ end | g_ last-char
Word: w next | b previous | e end
Search: f{char} | F{char} | t{char} | T{char} | ; | ,
Jump: gg top | G bottom | {n}G line | H/M/L screen
Find: /{pattern} | n next | N previous | * word | # word
Editing Quick Reference
Insert: i | I | a | A | o | O | s | S
Delete: x | X | dd | dw | db | D | d$ | d0
Change: cw | cc | C | c$ | ciw | ci" | ci{
Yank/Paste: yy | yw | y$ | p | P | "+y | "+p
Undo/Redo: u | Ctrl+r | U
Repeat: . (dot command)
Visual Mode Quick Reference
Enter: v char | V line | Ctrl+v block
Actions: d delete | c change | y yank | > indent | < outdent
Case: u lower | U upper | ~ toggle
Practice Exercises
Exercise 1: Navigation Basics
Open any code file and try:
- First line:
gg - Last line:
G - Line 50:
50G - Find βfunctionβ:
/function - Next match:
n - Previous match:
N
Exercise 2: Editing Workflow
Given:
const userName = 'JohnDoe'
Try:
- Change βJohnDoeβ to βJaneSmithβ:
ci"JaneSmith[Esc] - Change variable name:
ciwuserEmail[Esc] - Delete line:
dd - Undo:
u
Exercise 3: Text Objects
Given:
function greet(name) {
return 'Hello, ' + name + '!'
}
Try:
- Cursor on any char in βHello, β
- Change string:
ci"Goodbye[Esc] - Delete function body:
ci{[Esc] - Delete entire function:
da{
Exercise 4: Macro Recording
Task: Add // TODO: to the start of 5 lines.
qaβ start recordingI// TODO: [Esc]β insert at line startjβ move downqβ stop recording4@aβ repeat 4 more times
VIM Configuration Tips
Add these to your ~/.vimrc:
" Line numbers
set number
set relativenumber
" Search improvements
set ignorecase " Case-insensitive search
set smartcase " Case-sensitive if uppercase used
set incsearch " Incremental search
set hlsearch " Highlight search results
" Indentation
set expandtab " Use spaces instead of tabs
set tabstop=2 " Tab width = 2 spaces
set shiftwidth=2 " Indent width = 2 spaces
set autoindent " Auto-indent new lines
" Performance
set lazyredraw " Don't redraw during macros
" Quality of life
set clipboard=unnamedplus " Use system clipboard
set mouse=a " Enable mouse support
set scrolloff=8 " Keep 8 lines visible when scrolling
" Map leader key
let mapleader = " "
" Quick save and quit
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
" Clear search highlighting
nnoremap <leader>h :noh<CR>
Common Patterns and Workflows
Refactoring Variable Name
Rename userName to userEmail across a file:
:%s/userName/userEmail/gc
%β entire filegβ all occurrences per linecβ confirm each
Delete All Comments
Single-line comments (//):
:g/^[ \t]*\/\//d
Format JSON
:%!python -m json.tool
Remove Trailing Whitespace
:%s/\s\+$//
Swap Two Words
Cursor on first word:
dawwP
dawβ delete a wordwβ next wordPβ paste before
Conclusion
VIMβs power is composability: movements + actions + text objects combine into endless efficient edits.
Key Takeaways:
- Master movement first:
h/j/k/l,w/b,0/$,gg/G - Use text objects:
ciw,di",ci{are the big wins - Use the dot command:
.repeats your last change - Visual mode for complex edits: select, then operate
- Practice daily: muscle memory beats memorization
Next Steps:
- Run
vimtutorin your terminal - Practice 15 minutes daily for 2 weeks
- Learn one new command per day
- Use VIM keybindings in your IDE (VS Code, IntelliJ have VIM plugins)