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)