Tech Guides
REF DES: U1 — Modal Text Editor IC

VIM / NEOVIM

Modal Editor — Complete Reference
Vim 9.x / Neovim 0.10+
Normal
Insert
Visual
QR

Quick Reference

Essential commands at a glance. The most frequently used Vim operations organized by category.

Mode Switching

iInsert before cursor
aInsert after cursor
oNew line below
vVisual (char)
VVisual (line)
Ctrl+vVisual (block)
:Command-line mode
RReplace mode
EscReturn to Normal

Essential Motions

hjklLeft / Down / Up / Right
w / b / eWord fwd / back / end
0 / $Line start / end
^First non-blank
gg / GFile top / bottom
{ / }Paragraph prev / next
%Matching bracket
fc / tcFind / till char

Core Operations

d{motion}Delete
c{motion}Change (delete + insert)
y{motion}Yank (copy)
p / PPaste after / before
uUndo
Ctrl+rRedo
.Repeat last change
xDelete char

Text Objects

iw / awInner / around word
i" / a"Inner / around quotes
i( / a(Inner / around parens
i{ / a{Inner / around braces
it / atInner / around tags
is / asInner / around sentence
ip / apInner / around paragraph

Save & Quit

:wSave (write)
:qQuit
:wqSave and quit
:q!Quit without saving
ZZSave and quit (normal)
ZQQuit without saving (normal)
:waSave all buffers
:qaQuit all

Search & Replace

/patternSearch forward
?patternSearch backward
n / NNext / previous match
* / #Word under cursor fwd / back
:%s/old/new/gGlobal replace
:%s/old/new/gcReplace with confirm
01

Modes

Vim is a modal editor. Each mode changes how the keyboard behaves. Mastering mode transitions is the foundation of Vim fluency.

Mode Reference
Mode Enter Exit Purpose
Normal Esc or Ctrl+[ (default mode) Navigate, operate on text, compose commands
Insert i a o I A O s S c{motion} Esc Type text into the buffer
Visual v (char) V (line) Ctrl+v (block) Esc Select text for operations
Command-line : (Ex) / (search fwd) ? (search back) Esc or Enter Execute Ex commands, search
Replace R (overtype) r (single char) Esc Overwrite existing text in place

Insert Mode Entry Points

  • iInsert before cursor
  • IInsert at beginning of line (first non-blank)
  • aAppend after cursor
  • AAppend at end of line
  • oOpen new line below and enter insert
  • OOpen new line above and enter insert
  • sSubstitute character (delete char, enter insert)
  • SSubstitute line (delete line content, enter insert)
  • c{motion}Change: delete motion target and enter insert
  • CChange to end of line
  • giInsert at last insert position
TIP Use Ctrl+[ as a faster alternative to Esc. Many Vim users also remap Caps Lock to Esc or Ctrl at the OS level for ergonomics.
02

Movement & Navigation

Movement commands are the building blocks of Vim's composable editing language. Every motion can be combined with operators like d, c, and y.

Character & Word Motion

KeyActionNotes
hMove left
jMove down
kMove up
lMove right
wNext word startPunctuation-delimited
WNext WORD startWhitespace-delimited
bPrevious word start
BPrevious WORD start
eEnd of word
EEnd of WORD
geEnd of previous word

Line Motion

  • 0Move to first column (absolute start of line)
  • ^Move to first non-blank character
  • $Move to end of line
  • g_Move to last non-blank character
  • +First non-blank of next line
  • -First non-blank of previous line
  • {n}|Go to column n

Paragraph & File Motion

  • {Previous blank line (paragraph start)
  • }Next blank line (paragraph end)
  • (Previous sentence
  • )Next sentence
  • ggGo to first line of file
  • GGo to last line of file
  • {n}GGo to line n
  • {n}ggGo to line n (alternative)
  • %Jump to matching bracket/paren/brace

Screen Motion

  • HMove cursor to top of screen
  • MMove cursor to middle of screen
  • LMove cursor to bottom of screen
  • Ctrl+fScroll full page down
  • Ctrl+bScroll full page up
  • Ctrl+dScroll half page down
  • Ctrl+uScroll half page up
  • zzCenter current line on screen
  • ztMove current line to top of screen
  • zbMove current line to bottom of screen

Character Search (Within Line)

  • f{char}Jump to next occurrence of char on current line
  • F{char}Jump to previous occurrence of char on current line
  • t{char}Jump to just before next occurrence of char
  • T{char}Jump to just after previous occurrence of char
  • ;Repeat last f/F/t/T search
  • ,Repeat last f/F/t/T in reverse direction
TIP f and t are among Vim's most powerful motions. Use dt) to delete up to a closing paren, or cf" to change up to and including the next double quote.

Marks & Jumps

  • m{a-z}Set local mark (within file)
  • m{A-Z}Set global mark (across files)
  • '{mark}Jump to line of mark
  • `{mark}Jump to exact position of mark
  • ''Jump to last jump position (line)
  • ``Jump to last jump position (exact)
  • Ctrl+oJump to older position in jump list
  • Ctrl+iJump to newer position in jump list
  • g;Go to older position in change list
  • g,Go to newer position in change list
03

Editing Operations

Vim's editing grammar follows the pattern: [count][operator][count][motion/text-object]. Learn operators and motions separately, then combine them freely.

Delete

  • xDelete character under cursor
  • XDelete character before cursor
  • ddDelete entire line
  • DDelete from cursor to end of line
  • d{motion}Delete over motion (e.g., dw, d$, dgg)
  • d{text-obj}Delete text object (e.g., diw, da", dip)
  • {n}ddDelete n lines

Change

  • ccChange entire line (delete and enter insert)
  • CChange from cursor to end of line
  • c{motion}Change over motion (e.g., cw, c$)
  • c{text-obj}Change text object (e.g., ci", ca()
  • sSubstitute character (delete + insert, same as cl)
  • SSubstitute line (same as cc)
  • r{char}Replace single character (stays in normal mode)

Yank & Put (Copy & Paste)

  • yyYank (copy) entire line
  • YYank entire line (same as yy; Neovim maps to y$)
  • y{motion}Yank over motion (e.g., yw, y$)
  • y{text-obj}Yank text object (e.g., yiw, ya")
  • pPut (paste) after cursor / below line
  • PPut (paste) before cursor / above line
  • gpPut after and move cursor past pasted text
  • gPPut before and move cursor past pasted text

Undo, Redo & Repeat

  • uUndo last change
  • Ctrl+rRedo (undo the undo)
  • UUndo all changes on current line
  • .Repeat last change (the dot command)
  • {n}uUndo n changes
TIP The . command is one of Vim's most powerful features. Structure your edits so they are repeatable: for example, ciwreplacementEsc can be repeated on other words with just .

Indentation & Formatting

  • >>Indent current line
  • <<Outdent current line
  • >{motion}Indent over motion
  • ={motion}Auto-indent over motion
  • ==Auto-indent current line
  • gg=GAuto-indent entire file
  • JJoin current line with next (with space)
  • gJJoin lines without space
  • gq{motion}Format/rewrap text over motion
  • ~Toggle case of character
  • gU{motion}Uppercase over motion
  • gu{motion}Lowercase over motion
04

Text Objects

Text objects define structured regions of text. They are used with operators (d, c, y, v) and come in two flavors: inner (i) excludes delimiters, around (a) includes them.

Text Object Reference
Inner Around Selects Example Usage
iw aw Word ciw change inner word, daw delete word + surrounding space
iW aW WORD (whitespace-delimited) diW delete WORD including punctuation
is as Sentence das delete sentence and trailing space
ip ap Paragraph yap yank paragraph with surrounding blank lines
i" a" Double-quoted string ci" change text inside double quotes
i' a' Single-quoted string di' delete text inside single quotes
i` a` Backtick-quoted string ci` change inside backticks
i( or ib a( or ab Parentheses di( delete inside parens
i[ a[ Square brackets ci[ change inside brackets
i{ or iB a{ or aB Curly braces daB delete braces and their content
i< a< Angle brackets ci< change inside angle brackets
it at HTML/XML tags cit change inner tag content, dat delete entire tag
TIP Text objects work from anywhere inside the delimiters -- you don't need to position your cursor at the start. ci" from anywhere inside a quoted string will change its entire content. This is why text objects are often faster than motions.
Example: Text Object Combinations
# Given: function("hello world", 42)
#                  ^cursor here

ci"         # Changes "hello world" to whatever you type
da(         # Deletes ("hello world", 42) including parens
yi(         # Yanks: "hello world", 42

# Given: <div class="box">content here</div>
#                          ^cursor here

cit         # Changes "content here" inside the tags
dat         # Deletes the entire <div>...</div>
vat         # Visually selects the entire tag block
05

Visual Mode

Visual mode lets you select text and then perform operations on the selection. Three sub-modes cover character, line, and block (column) selections.

Entering Visual Mode

  • vCharacter-wise visual mode
  • VLine-wise visual mode
  • Ctrl+vBlock-wise (column) visual mode
  • gvRe-select the last visual selection

Visual Mode Navigation

  • oMove to other end of selection
  • OMove to other corner of block selection
  • All motionsh/j/k/l, w/b/e, 0/$, etc. extend the selection
  • Text objectsiw, a", ip, etc. expand selection to match

Operations on Visual Selections

  • dDelete selection
  • cChange selection (delete + enter insert)
  • yYank (copy) selection
  • > / <Indent / outdent selection
  • =Auto-indent selection
  • ~Toggle case
  • U / uUppercase / lowercase selection
  • JJoin selected lines
  • gqFormat/rewrap selected text
  • r{char}Replace every character in selection with char
  • :Enter command-line with range for selection

Visual Block Operations

Visual Block mode (Ctrl+v) enables powerful column editing. Select a rectangular block, then use these commands:

  • IInsert before block on every line (type, then Esc)
  • AAppend after block on every line
  • cChange block content on every line
  • r{char}Replace entire block with char
  • dDelete the block
  • $Extend block to end of each line (ragged right)
Example: Add Comment Prefix to Multiple Lines
# 1. Position cursor at start of first line
# 2. Ctrl+v to enter visual block
# 3. j j j to extend selection down 3 lines
# 4. I to insert before block
# 5. Type "// " (comment prefix)
# 6. Esc -- all 4 lines now have "// " prepended
07

Registers & Macros

Registers are Vim's named storage slots. They hold yanked/deleted text, macros, and special values. Macros record and replay sequences of keystrokes.

Register Types

RegisterNameDescription
""Default (unnamed)Last delete or yank goes here
"0Yank registerLast yank only (not affected by deletes)
"1 - "9NumberedDelete history (1=most recent, shifts down)
"a - "zNamedUser-controlled, explicit storage
"A - "ZAppend to namedAppend to existing register content
"+System clipboardOS clipboard (requires clipboard support)
"*Selection clipboardX11 primary selection (Linux)
"_Black holeDelete without affecting any register
"/Last searchContains the last search pattern
":Last commandContains the last Ex command
".Last insertContains text from last insert
"=ExpressionEvaluate expression and use result
"%Current filenameName of the current file

Using Registers

  • "{reg}y{motion}Yank into specific register (e.g., "ayiw)
  • "{reg}d{motion}Delete into specific register
  • "{reg}pPaste from specific register
  • "0pPaste last yank (unaffected by deletes)
  • "_ddDelete line without saving to any register
  • "+yYank to system clipboard
  • "+pPaste from system clipboard
  • :regView contents of all registers
  • :reg abcView contents of registers a, b, c
TIP "0p is essential: after yanking then deleting, p pastes the delete, but "0p always pastes the last yank. This solves the common "I yanked something, then deleted something else, and now I can't paste what I yanked" problem.

Macros

Macros record a sequence of keystrokes into a register, then replay them. They are Vim's most powerful automation tool.

  • q{a-z}Start recording macro into register
  • qStop recording
  • @{a-z}Play macro from register
  • @@Replay the last played macro
  • {n}@{a-z}Play macro n times
  • :'<,'>norm @aPlay macro on each line of visual selection
  • :5,20norm @aPlay macro on lines 5 through 20
Macro Recording Example
# Goal: Wrap each word in quotes on a list of words
# Before: apple, banana, cherry
# After:  "apple", "banana", "cherry"

# Record macro:
qa              # Start recording into register a
f,              # Find next comma (or use w to move)
i"<Esc>        # Insert quote before word
ea"<Esc>        # Append quote after word
q               # Stop recording

# Then: @a to play, or 10@a to repeat 10 times
08

Windows, Tabs & Buffers

Vim uses three layers of view management: buffers (open files), windows (viewport splits), and tabs (collections of windows). A buffer can be displayed in multiple windows.

Window Splits

  • Ctrl+w sHorizontal split (same file)
  • Ctrl+w vVertical split (same file)
  • :sp fileHorizontal split with file
  • :vsp fileVertical split with file
  • :newHorizontal split with new empty buffer
  • :vnewVertical split with new empty buffer

Window Navigation

  • Ctrl+w hMove to window left
  • Ctrl+w jMove to window below
  • Ctrl+w kMove to window above
  • Ctrl+w lMove to window right
  • Ctrl+w wCycle through windows
  • Ctrl+w pGo to previous (last accessed) window

Window Resizing & Moving

  • Ctrl+w =Make all windows equal size
  • Ctrl+w _Maximize height of current window
  • Ctrl+w |Maximize width of current window
  • Ctrl+w +Increase height
  • Ctrl+w -Decrease height
  • Ctrl+w >Increase width
  • Ctrl+w <Decrease width
  • Ctrl+w HMove window to far left
  • Ctrl+w JMove window to bottom
  • Ctrl+w KMove window to top
  • Ctrl+w LMove window to far right
  • Ctrl+w TMove window to new tab

Window Close

  • Ctrl+w qClose current window (quit if last)
  • Ctrl+w cClose current window (never quits Vim)
  • Ctrl+w oClose all other windows (only keep current)

Tabs

  • :tabnewOpen new tab
  • :tabnew fileOpen file in new tab
  • :tabcClose current tab
  • :taboClose all other tabs
  • gtGo to next tab
  • gTGo to previous tab
  • {n}gtGo to tab n (1-indexed)
  • :tabsList all tabs

Buffers

  • :e fileOpen file in current window
  • :lsList all open buffers
  • :bnGo to next buffer
  • :bpGo to previous buffer
  • :b{n}Go to buffer number n
  • :b nameGo to buffer by partial filename match
  • :bdDelete (close) current buffer
  • :bd{n}Delete buffer number n
  • :bufdo cmdExecute command in all buffers
09

File Operations

Opening, saving, reading, and managing files from within Vim.

Open, Save & Close

  • :e fileEdit (open) file
  • :e!Reload current file (discard changes)
  • :e .Open file browser (Netrw) in current directory
  • :wWrite (save) current file
  • :w fileWrite to a different filename (save as)
  • :w!Force write (override read-only)
  • :saveas fileSave as new filename and switch to it
  • :r fileRead file and insert content below cursor
  • :r !cmdInsert output of shell command below cursor

Netrw (Built-in File Browser)

  • :ExOpen Netrw in current file's directory
  • :SexOpen Netrw in horizontal split
  • :VexOpen Netrw in vertical split
  • :LexOpen Netrw in left sidebar split

Inside Netrw:

  • EnterOpen file or directory
  • -Go up one directory
  • %Create new file
  • dCreate new directory
  • DDelete file or directory
  • RRename file
  • iCycle listing style (thin/long/wide/tree)

File Navigation Shortcuts

  • gfGo to file under cursor
  • gFGo to file under cursor at line number
  • gdGo to local declaration of word under cursor
  • gDGo to global declaration of word under cursor
  • Ctrl+^Switch to alternate (previous) file
  • :find fileSearch for file in path and open it
10

Command-Line Mode

Ex commands accessed with : provide powerful file-wide and multi-file operations. Most accept ranges to specify which lines to act on.

Ranges

RangeMeaning
.Current line
$Last line of file
%Entire file (same as 1,$)
5Line 5
5,20Lines 5 through 20
.,+5Current line through 5 lines below
'<,'>Visual selection (auto-inserted)
'a,'bFrom mark a to mark b

Essential Ex Commands

  • :dDelete lines (e.g., :5,10d)
  • :m{dest}Move lines to destination (e.g., :5,10m$)
  • :co{dest}Copy lines to destination (e.g., :5,10co20)
  • :norm {cmds}Execute normal mode commands on range (e.g., :%norm A;)
  • :sortSort lines alphabetically
  • :sort!Sort in reverse
  • :sort uSort and remove duplicates
  • :sort nSort numerically

Shell Integration

  • :!cmdExecute shell command (e.g., :!ls)
  • :r !cmdInsert output of command into buffer
  • :w !cmdPipe buffer to command as stdin
  • :{range}!cmdFilter range through command (replace lines with output)
  • :sh / :terminalOpen a shell / terminal inside Vim
  • Ctrl+zSuspend Vim to shell; fg to return
Shell Filter Examples
# Sort selected lines through external sort
:'<,'>!sort

# Format JSON in buffer using jq
:%!jq .

# Run current Python file
:!python %

# Insert today's date below cursor
:r !date

# Pipe visual selection to clipboard
:'<,'>w !pbcopy

Command-Line History & Editing

  • q:Open command-line history window
  • q/Open search history window
  • Ctrl+fSwitch from : prompt to editable history window
  • Up / DownCycle through command history
  • @:Repeat last Ex command
11

Neovim Specifics

Neovim extends Vim with built-in LSP, Tree-sitter, Lua scripting, and a rich plugin ecosystem. These features make Neovim a full-fledged IDE.

Built-in LSP (Language Server Protocol)

Neovim's built-in LSP client provides IDE features. Configure with nvim-lspconfig plugin and bind these functions:

Lua FunctionActionCommon Binding
vim.lsp.buf.definition()Go to definitiongd
vim.lsp.buf.declaration()Go to declarationgD
vim.lsp.buf.hover()Show hover docsK
vim.lsp.buf.implementation()Go to implementationgi
vim.lsp.buf.references()Find referencesgr
vim.lsp.buf.rename()Rename symbol<leader>rn
vim.lsp.buf.code_action()Code actions<leader>ca
vim.lsp.buf.format()Format buffer/range<leader>f
vim.diagnostic.goto_next()Next diagnostic]d
vim.diagnostic.goto_prev()Previous diagnostic[d

Tree-sitter

Tree-sitter provides fast, incremental parsing for syntax highlighting, code folding, text objects, and more.

  • :TSInstall langInstall parser for language
  • :TSUpdateUpdate all installed parsers
  • :InspectTreeView syntax tree (Neovim 0.10+)

Tree-sitter enables smart text objects like function parameters, class bodies, and conditionals via nvim-treesitter-textobjects.

Lua API Essentials

Common Lua API Patterns
-- Set options
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true

-- Set keymaps
vim.keymap.set('n', '<leader>w', ':w<CR>', { desc = 'Save file' })
vim.keymap.set('n', '<leader>q', ':q<CR>', { desc = 'Quit' })
vim.keymap.set('n', '<Esc>', ':noh<CR>', { desc = 'Clear highlights' })

-- Set leader key (must be before lazy.nvim setup)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

-- Autocommands
vim.api.nvim_create_autocmd('BufWritePre', {
    pattern = '*',
    callback = function()
        vim.cmd [[%s/\s\+$//e]]
    end,
})

-- Run Vim commands from Lua
vim.cmd('colorscheme habamax')
vim.cmd.colorscheme('habamax')  -- alternative syntax

Key Plugins (Neovim Ecosystem)

PluginPurpose
lazy.nvimPlugin manager (lazy-loading, lockfile, UI)
nvim-lspconfigLSP server configurations
nvim-cmpAutocompletion engine
telescope.nvimFuzzy finder (files, grep, buffers, etc.)
nvim-treesitterTree-sitter integration
mason.nvimLSP/DAP/linter/formatter installer
gitsigns.nvimGit integration (hunks, blame, signs)
neo-tree.nvimFile explorer sidebar
which-key.nvimKeymap hints popup
nvim-dapDebug Adapter Protocol client
lazy.nvim Bootstrap (init.lua)
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        'git', 'clone', '--filter=blob:none',
        'https://github.com/folke/lazy.nvim.git',
        '--branch=stable', lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)

-- Setup plugins
require('lazy').setup({
    { 'neovim/nvim-lspconfig' },
    { 'nvim-telescope/telescope.nvim', dependencies = { 'nvim-lua/plenary.nvim' } },
    { 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate' },
    -- Add more plugins here
})
12

Configuration

Essential settings for both Vim (~/.vimrc) and Neovim (~/.config/nvim/init.lua). These form a solid baseline for any setup.

Vimscript (.vimrc)

Essential .vimrc Settings
" === UI ===
set number                " Show line numbers
set relativenumber        " Relative line numbers
set cursorline            " Highlight current line
set signcolumn=yes        " Always show sign column
set scrolloff=8           " Keep 8 lines visible above/below cursor
set sidescrolloff=8       " Keep 8 columns visible left/right
set colorcolumn=80        " Show column guide at 80
set showmode              " Show current mode
set showcmd               " Show partial command
set laststatus=2          " Always show status line
set wildmenu              " Enhanced command-line completion
set wildmode=longest:full,full

" === Search ===
set hlsearch              " Highlight search results
set incsearch             " Incremental search
set ignorecase            " Case-insensitive search...
set smartcase             " ...unless uppercase is used

" === Tabs & Indentation ===
set tabstop=4             " Tab width = 4 spaces
set shiftwidth=4          " Indent width = 4 spaces
set expandtab             " Use spaces instead of tabs
set smartindent           " Smart auto-indentation
set autoindent            " Copy indent from current line

" === Behavior ===
set hidden                " Allow hidden buffers with changes
set mouse=a               " Enable mouse in all modes
set clipboard=unnamedplus " Use system clipboard
set splitright            " New vertical splits go right
set splitbelow            " New horizontal splits go below
set undofile              " Persistent undo across sessions
set noswapfile            " Disable swap files
set updatetime=250        " Faster CursorHold events
set timeoutlen=300        " Faster key sequence timeout

" === Leader Key ===
let mapleader = " "       " Space as leader key

" === Key Mappings ===
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <Esc> :noh<CR>
nnoremap <leader>e :Ex<CR>

" Move lines up/down
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv

" Keep cursor centered on search navigation
nnoremap n nzzzv
nnoremap N Nzzzv

Lua Config (init.lua)

Essential init.lua Settings
-- Leader key (set before plugins)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

-- UI
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.cursorline = true
vim.opt.signcolumn = 'yes'
vim.opt.scrolloff = 8
vim.opt.sidescrolloff = 8
vim.opt.colorcolumn = '80'
vim.opt.termguicolors = true
vim.opt.showmode = false     -- hide mode (use statusline)

-- Search
vim.opt.hlsearch = true
vim.opt.incsearch = true
vim.opt.ignorecase = true
vim.opt.smartcase = true

-- Tabs & Indentation
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.smartindent = true

-- Behavior
vim.opt.hidden = true
vim.opt.mouse = 'a'
vim.opt.clipboard = 'unnamedplus'
vim.opt.splitright = true
vim.opt.splitbelow = true
vim.opt.undofile = true
vim.opt.swapfile = false
vim.opt.updatetime = 250
vim.opt.timeoutlen = 300

-- Keymaps
local map = vim.keymap.set
map('n', '<leader>w', ':w<CR>', { desc = 'Save' })
map('n', '<leader>q', ':q<CR>', { desc = 'Quit' })
map('n', '<Esc>', ':noh<CR>', { desc = 'Clear search' })
map('n', '<leader>e', ':Ex<CR>', { desc = 'File explorer' })

-- Move lines in visual mode
map('v', 'J', ":m '>+1<CR>gv=gv", { desc = 'Move line down' })
map('v', 'K', ":m '<-2<CR>gv=gv", { desc = 'Move line up' })

-- Keep cursor centered
map('n', 'n', 'nzzzv')
map('n', 'N', 'Nzzzv')
map('n', '<C-d>', '<C-d>zz')
map('n', '<C-u>', '<C-u>zz')
13

Pro Tips

Advanced techniques and mental models that separate Vim beginners from power users.

The Dot Formula

The . command repeats the last change. Structure your edits to maximize repeatability: use one atomic editing command that captures the full intent of your change.

Dot Formula in Action
# BAD: Multiple steps, not repeatable as one unit
f"lr'f"lr'       # Find quote, replace, find next, replace

# GOOD: Repeatable single change
f"r'             # Replace one quote...
;.               # ; repeats f", . repeats r'  --  pure magic!

# BEST: Use :s for bulk, but for scattered edits:
ciw<new_word>Esc  # Change word, then use n. to find-and-replace
                   # (after searching with * first)

The cgn Trick (Search + Change + Repeat)

One of Vim's most powerful patterns. gn is a motion that selects the next search match. Combined with c, it becomes a targeted find-and-replace you control with .

cgn Workflow
# Step 1: Search for the target
/oldFunction     # or use * on the word

# Step 2: Change first occurrence
cgn              # Deletes match and enters insert mode
newFunction      # Type replacement
Esc              # Back to normal mode

# Step 3: Repeat selectively
.                # Changes next match automatically
.                # And the next...
n                # Skip one (don't change it)
.                # Change this one

# Why this is better than :%s/old/new/gc:
# - You see each change in context before deciding
# - Works across multiple files with :bufdo
# - Fully undoable one at a time

Operator + Motion Grammar

Vim's editing language follows a grammar: [count] operator [count] motion/text-object. Learning operators and motions separately gives you multiplicative power.

Operators x Motions = Combinations
w word$ endiw inner wordi" inner quotesip inner para
d deletedwd$diwdi"dip
c changecwc$ciwci"cip
y yankywy$yiwyi"yip
v selectvwv$viwvi"vip
> indent>w>$>iw>i">ip
gU uppergUwgU$gUiwgUi"gUip
KEY With 6 operators and 20+ motions/text objects, you get 120+ editing commands from memorizing ~26 things. Every new operator works with every existing motion, and vice versa. This composability is Vim's core design insight.

Visual Block Magic

Multi-line Editing Patterns
# Add text to multiple lines at once:
Ctrl+v           # Enter visual block
jjjj             # Select 5 lines
I                # Insert mode (at block start)
const            # Type prefix
Esc              # Applied to all 5 lines!

# Append to lines of different lengths:
Ctrl+v           # Enter visual block
jjjj             # Select lines
$                # Extend to end of each line
A                # Append mode
;                # Type suffix
Esc              # Applied to all lines!

# Change column of text:
Ctrl+v           # Enter visual block
jjjj             # Select block region
llll             # Extend selection right
c                # Change block
newtext          # Type replacement
Esc              # Applied to all lines!

Register Power Moves

  • "0pAlways paste last yank (ignore deletes)
  • "_d{motion}True delete: send to black hole, preserve registers
  • "+y{motion}Yank to system clipboard
  • "ayy then "AyyAccumulate lines in register a (lowercase sets, uppercase appends)
  • Ctrl+r {reg}Insert register contents in insert/command-line mode
  • Ctrl+r =Evaluate expression and insert result (calculator!)

Useful g Commands

  • gvRe-select last visual selection
  • giEnter insert at last insert position
  • gfOpen file under cursor
  • gdGo to local definition
  • gDGo to global definition
  • gU{motion}Make uppercase
  • gu{motion}Make lowercase
  • g~{motion}Toggle case
  • gnSelect next search match (for cgn pattern)
  • g;Go to older position in change list
  • g,Go to newer position in change list
  • g&Repeat last :s on entire file
  • gq{motion}Format/rewrap text
  • gaShow ASCII/Unicode value of char under cursor
  • g8Show UTF-8 byte sequence of char under cursor
  • gJJoin lines without space

Insert Mode Shortcuts

You don't always need to leave insert mode to perform quick actions:

  • Ctrl+wDelete word before cursor
  • Ctrl+uDelete to start of line
  • Ctrl+hDelete character before cursor (same as backspace)
  • Ctrl+tIndent current line
  • Ctrl+dOutdent current line
  • Ctrl+r {reg}Insert contents of register
  • Ctrl+aRe-insert last inserted text
  • Ctrl+oExecute one normal mode command, then return to insert
  • Ctrl+n / Ctrl+pAutocomplete (next/previous match)