Introduction

VIM is one of the most powerful text editors available, but its modal nature can be intimidating for beginners. Once you master the basic movements and commands, you’ll find yourself editing text at lightning speed without ever reaching for the mouse.

This guide covers the essential VIM shortcuts that will dramatically improve your editing speed.

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

Before diving into shortcuts, understand VIM’s modes:

ModeDescriptionHow to Enter
NormalNavigate and execute commandsEsc
InsertType text like a regular editori, a, o
VisualSelect textv, V, Ctrl+v
CommandExecute Ex commands:

Golden Rule: Always return to Normal mode after editing. Hit Esc frequently!


Basic Movement (Normal Mode)

Character-Level Movement

CommandActionExample
hMove leftMove 1 character left
lMove rightMove 1 character right
jMove downMove 1 line down
kMove upMove 1 line up
Mnemonic: Think of j as a down arrow (↓) and k as an up arrow (↑).

Fast Movement Within Lines

CommandActionUse Case
0Start of line (column 0)Jump to very beginning
^First non-blank characterSkip indentation
$End of lineJump to line end
g_Last non-blank characterSkip trailing spaces

Example:

    const message = "Hello World";
  • 0 → moves to column 0 (before spaces)
  • ^ → moves to ‘c’ in ‘const’
  • $ → moves after ’;’ and spaces
  • g_ → moves to ’;‘

Word-Level Movement

CommandActionExample
wNext word (forward)constmessage
bPrevious word (backward)messageconst
eEnd of wordMove to last char of word
WNext WORD (space-delimited)Skip punctuation
BPrevious WORDBackward, skip punctuation

Difference between w and W:

const user.name = "John-Doe";
  • w: treats user, ., name, =, ", John, -, Doe as separate words
  • W: treats user.name, =, "John-Doe" as WORDS (space-delimited)

Line-Level Movement

CommandActionTip
ggFirst line of fileJump to top
GLast line of fileJump to bottom
42G or :42Line 42Go to specific line
50%50% of fileJump to middle
HTop of screen (High)Visible area only
MMiddle of screenVisible area only
LBottom of screen (Low)Visible area only

Search-Based Movement

CommandActionExample
f{char}Find forward to charfa → find next ‘a’
F{char}Find backward to charFa → 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/TFind next occurrence
,Reverse last f/t/F/TFind 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 ?

CommandActionNotes
/patternSearch forwardType pattern, press Enter
?patternSearch backwardReverse search
nNext matchSame direction
NPrevious matchOpposite direction
*Search word under cursor (forward)Quick search
#Search word under cursor (backward)Quick search

Example Workflow:

  1. Place cursor on variable name userName
  2. Press * → highlights all occurrences
  3. Press n → jump to next occurrence
  4. Press N → jump back

Fast Editing (Normal Mode)

Insert Mode Shortcuts

CommandActionCursor Position
iInsert before cursorCurrent position
IInsert at line startFirst non-blank char
aAppend after cursorOne char right
AAppend at line endEnd of line
oOpen line belowNew line below
OOpen line aboveNew line above
sSubstitute charDelete char + insert
SSubstitute lineDelete line + insert

Efficiency Tip: Use A instead of $a and I instead of ^i.

Deletion Commands

CommandActionMemory Aid
xDelete characterCut char under cursor
XDelete char beforeBackspace in normal mode
ddDelete lineCut entire line
dwDelete wordFrom cursor to word end
dbDelete word backwardTo word start
d$ or DDelete to line endFrom cursor to EOL
d0Delete to line startFrom cursor to start
dGDelete to file endFrom cursor to EOF
dggDelete to file startFrom cursor to top

Change Commands (Delete + Insert)

CommandActionEquivalent
cwChange worddwi
c$ or CChange to line endd$i
cc or SChange entire lineddi
ciwChange inner wordDelete word under cursor
ci"Change inside quotesReplace text in ”…”
ci{Change inside bracesReplace text in {...}
citChange inside tagReplace HTML tag content

Example:

const message = 'Hello World'
  • Cursor on any char in “Hello World”
  • Type ci" → deletes “Hello World”, enters insert mode
  • Type new text → "New Message"

Copy (Yank) and Paste

CommandActionNotes
yy or YYank (copy) lineCopy entire line
ywYank wordFrom cursor to word end
y$Yank to line endFrom cursor to EOL
yggYank to file startFrom cursor to top
yGYank to file endFrom cursor to bottom
pPaste after cursorPaste below line
PPaste before cursorPaste above line

System Clipboard:

  • "+y → Copy to system clipboard
  • "+p → Paste from system clipboard

Undo and Redo

CommandAction
uUndo last change
Ctrl+rRedo (undo the undo)
UUndo all changes on line

Repeat Last Command

CommandActionUse Case
.Repeat last changeSuper powerful!

Example:

  1. Type dw → delete word
  2. Move to another word
  3. Type . → deletes that word too

This works with any change: dd, ciw, x, etc.


Visual Mode Shortcuts

Entering Visual Mode

CommandModeSelection Type
vVisualCharacter-wise
VVisual LineLine-wise
Ctrl+vVisual BlockColumn-wise (rectangle)

Operating on Visual Selections

After selecting text in visual mode:

CommandAction
dDelete selection
cChange selection
yYank (copy) selection
>Indent right
<Indent left
=Auto-indent
uLowercase
UUppercase
~Toggle case

Example - Comment Multiple Lines:

  1. Ctrl+v → enter visual block mode
  2. jjj → select 4 lines (down 3 times)
  3. I → insert at start of block
  4. # → type comment character
  5. Esc → apply to all lines

Text Objects (Game Changer!)

Text objects let you operate on logical units of text.

Syntax

PatternMeaning
iInner (excludes delimiters)
aAround (includes delimiters)

Common Text Objects

ObjectDescriptionExample
iwInner wordWord under cursor
awA word (with space)Word + trailing space
isInner sentenceCurrent sentence
asA sentenceSentence + space
ipInner paragraphParagraph (blank-delimited)
apA paragraphParagraph + blank line
i"Inner quotesText inside ”…”
a"Around quotesText + ”…”
i( or ibInner parenthesesText inside (…)
a( or abAround parenthesesText + (…)
i{ or iBInner bracesText inside {...}
a{ or aBAround bracesText + {...}
itInner tagInside HTML tag
atAround tagHTML tag + content

Powerful Combinations

CommandActionExample
ciwChange inner wordReplace word
dawDelete a wordDelete word + space
di"Delete inside quotesClear “text”
da"Delete around quotesRemove “text” entirely
ci{Change inside bracesReplace {...} content
ditDelete inside tagClear <p>text</p>
vitSelect inside tagSelect tag content
yipYank inner paragraphCopy paragraph

Real-World Example:

const user = {
  name: 'John Doe',
  email: '[email protected]',
}
  • Cursor anywhere inside {...}
  • Type ci{ → deletes content, stays in {...}
  • Type new object content

Search and Replace

Basic Find/Replace

CommandActionScope
:s/old/new/Replace first on lineCurrent line
:s/old/new/gReplace all on lineCurrent line
:%s/old/new/gReplace all in fileEntire file
:%s/old/new/gcReplace with confirmationInteractive
:5,10s/old/new/gReplace in lines 5-10Range

Visual Selection Replace

  1. Select text with v or V
  2. Type : (shows :'<,'>)
  3. Type s/old/new/g
  4. Press Enter
CommandAction
/pattern\cCase-insensitive search
/pattern\CCase-sensitive search
:set icSet ignore case globally
:set noicTurn off ignore case

Numbers as Multipliers

You can prefix almost any command with a number to repeat it.

CommandAction
5jMove down 5 lines
3wMove forward 3 words
10ddDelete 10 lines
2yyYank 2 lines
4xDelete 4 characters
80i-[Esc]Insert 80 dashes
3pPaste 3 times
5>>Indent 5 lines right

Practical Example:

# Need to insert 50 equals signs
50i=[Esc]

Result: ==================================================

Marks and Jumps

Marks (Bookmarks)

CommandActionScope
maSet mark ‘a’Local to file
mASet mark ‘A’Global (across files)
`aJump to mark ‘a’Exact position
'aJump to line of mark ‘a’First non-blank
:marksList all marksShow marks

Jump List

CommandAction
Ctrl+oJump to older position
Ctrl+iJump to newer position
:jumpsShow jump list

Change List

CommandAction
g;Jump to older change position
g,Jump to newer change position
:changesShow change list

Window and Buffer Management

Split Windows

CommandAction
:split or :spHorizontal split
:vsplit or :vspVertical split
Ctrl+w sHorizontal split
Ctrl+w vVertical split
Ctrl+w wSwitch to next window
Ctrl+w h/j/k/lNavigate windows
Ctrl+w qClose current window
Ctrl+w =Equalize window sizes

Buffer Navigation

CommandAction
:ls or :buffersList all buffers
:b 2Switch to buffer 2
:bnNext buffer
:bpPrevious buffer
:bdDelete (close) buffer
:b filenameSwitch to buffer by name

Advanced Efficiency Tips

Macros (Record and Replay)

CommandAction
qaStart recording to register ‘a’
qStop recording
@aPlay macro from register ‘a’
@@Repeat last macro
5@aPlay macro ‘a’ 5 times

Example - Add semicolons to multiple lines:

  1. qa → start recording to register ‘a’
  2. A;[Esc] → append semicolon to end of line
  3. j → move down
  4. q → stop recording
  5. 10@a → repeat 10 times

Global Commands

CommandActionExample
:g/pattern/dDelete lines matching patternRemove all console.log
:v/pattern/dDelete lines not matching patternKeep only pattern
:g/TODO/pPrint lines matching patternFind all TODOs
:g/^$/dDelete empty linesClean 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

CommandAction
:sortSort lines alphabetically
:sort!Sort in reverse
:sort uSort and remove duplicates
:%!sortSort using external command

Auto-Completion (Insert Mode)

CommandCompletion Type
Ctrl+nNext word completion
Ctrl+pPrevious word completion
Ctrl+x Ctrl+fFile name completion
Ctrl+x Ctrl+lLine 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 practice:

  1. Jump to first line: gg
  2. Jump to last line: G
  3. Go to line 50: 50G
  4. Find word “function”: /function
  5. Next match: n
  6. Jump back: N

Exercise 2: Editing Workflow

Given this line:

const userName = 'JohnDoe'

Practice:

  1. Change “JohnDoe” to “JaneSmith”: ci"JaneSmith[Esc]
  2. Change variable name: ciwuserEmail[Esc]
  3. Delete entire line: dd
  4. Undo: u

Exercise 3: Text Objects

Given:

function greet(name) {
  return 'Hello, ' + name + '!'
}

Practice:

  1. Cursor on any char in “Hello, ”
  2. Change string: ci"Goodbye[Esc]
  3. Delete function content: ci{[Esc]
  4. Delete entire function: da{

Exercise 4: Macro Recording

Task: Add // TODO: to start of 5 lines

  1. qa → start recording
  2. I// TODO: [Esc] → insert at line start
  3. j → move down
  4. q → stop recording
  5. 4@a → repeat 4 more times

VIM Configuration Tips

Add these to your ~/.vimrc for better experience:

" 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

Scenario: Rename userName to userEmail in entire file

:%s/userName/userEmail/gc
  • % → entire file
  • g → all occurrences per line
  • c → confirm each change

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 word
  • w → move to next word
  • P → paste before

Conclusion

VIM’s power comes from composability: movements + actions + text objects create an infinite combination of efficient edits.

Key Takeaways:

  1. Master Movement First: Learn h/j/k/l, w/b, 0/$, gg/G
  2. Use Text Objects: ciw, di", ci{ are game-changers
  3. Embrace the Dot: The . command repeats your last change
  4. Visual Mode for Complex Edits: Select, then operate
  5. Practice Daily: Muscle memory beats memorization

Next Steps:

  • Install vimtutor: Run vimtutor in terminal
  • Practice 15 minutes daily for 2 weeks
  • Learn one new motion/command per day
  • Use VIM keybindings in your IDE (VS Code, IntelliJ have VIM extensions)

Happy VIM-ing! 🚀

References