Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

Vim

A highly configurable modal text editor designed for efficient text editing and manipulation.

Vim

A highly configurable modal text editor designed for efficient text editing and manipulation.

Overview

Vim (Vi IMproved) is a powerful text editor that operates through distinct modes, each optimised for different tasks. Its modal nature allows for complex text manipulation with minimal keystrokes, making it exceptionally efficient once mastered. Vim's philosophy centres on keeping your hands on the home row and composing commands from verbs (actions), modifiers, and objects.

vim filei, a, o, etc.v, V, Ctrl-vpress colonEscEscEnter/EscNormalInsertVisualCommandDefault modeText entrySelectionEx commandsvim filei, a, o, etc.v, V, Ctrl-vpress colonEscEscEnter/EscNormalInsertVisualCommandDefault modeText entrySelectionEx commands

Modes

Vim operates in distinct modes, each serving a specific purpose. Understanding modes is fundamental to using Vim effectively.

Key Concepts

Mode Purpose How to Enter How to Exit
Normal Navigation, manipulation Default / Esc N/A
Insert Text entry i, a, o, I, A, O Esc
Visual Text selection v, V, Ctrl-v Esc
Command Ex commands : Enter or Esc
Replace Overwrite text R Esc

Common Commands/Patterns

# Entering Insert mode
i       " Insert before cursor
I       " Insert at beginning of line
a       " Append after cursor
A       " Append at end of line
o       " Open new line below
O       " Open new line above

# Entering Visual mode
v       " Character-wise visual
V       " Line-wise visual
Ctrl-v  " Block-wise visual

# Entering Command mode
:       " Enter command-line mode
/       " Forward search (also command mode)
?       " Backward search (also command mode)

# Return to Normal mode
Esc     " Return from any mode
Ctrl-[  " Alternative to Esc
Ctrl-c  " Alternative to Esc (may cancel operations)

Examples

" Quickly fix a typo
ciw                   " Change inner word - deletes word and enters Insert mode
" Type the corrected word
Esc                   " Return to Normal mode

" Select and replace multiple lines
Vjj                   " Visual select 3 lines
:s/old/new/g         " Replace on selected lines

" Block editing (add comment to multiple lines)
Ctrl-v                " Enter block visual mode
jjj                   " Select 4 lines down
I                     " Insert at beginning of block
# <Esc>               " Add '# ' to all selected lines

Basic Navigation

Efficient movement is one of Vim's greatest strengths. Master these commands to navigate files without touching the mouse.

Key Concepts

Navigation in Vim operates at multiple levels:

  • Character level: Single character movement
  • Word level: Jump by words
  • Line level: Move within or between lines
  • Screen level: Navigate viewport
  • File level: Jump to specific locations
Filegg - file startG - file endnG - line nLine0 - line start^ - first non-blank$ - line endWordw - next wordb - previous worde - end of wordW - next WORDB - previous WORDCharacterh - leftj - downk - upl - rightFilegg - file startG - file endnG - line nLine0 - line start^ - first non-blank$ - line endWordw - next wordb - previous worde - end of wordW - next WORDB - previous WORDCharacterh - leftj - downk - upl - right

Common Commands/Patterns

# Character movement (Normal mode)
h       " Move left
j       " Move down
k       " Move up
l       " Move right

# Word movement
w       " Next word start (punctuation separated)
W       " Next WORD start (whitespace separated)
b       " Previous word start
B       " Previous WORD start
e       " End of current/next word
E       " End of current/next WORD
ge      " End of previous word

# Line movement
0       " Beginning of line
^       " First non-blank character
$       " End of line
g_      " Last non-blank character

# File movement
gg      " First line of file
G       " Last line of file
5G      " Go to line 5
:5      " Go to line 5 (command mode)
50%     " Go to 50% of file

# Screen movement
H       " Top of screen (High)
M       " Middle of screen
L       " Bottom of screen (Low)
Ctrl-u  " Half page up
Ctrl-d  " Half page down
Ctrl-f  " Full page forward
Ctrl-b  " Full page backward

# Within line
f{char} " Find character forward
F{char} " Find character backward
t{char} " Till character forward
T{char} " Till character backward
;       " Repeat f/F/t/T forward
,       " Repeat f/F/t/T backward

Examples

" Jump to a specific function in code
/def process<CR>      " Search for function definition
n                     " Next match
N                     " Previous match

" Navigate a long config file
gg                    " Go to top
/server<CR>           " Find server section
}                     " Jump to next paragraph/section
{                     " Jump to previous paragraph

" Move precisely within a line
f(                    " Jump to opening parenthesis
ci(                   " Change inside parentheses

" Using counts for efficient movement
5j                    " Move 5 lines down
3w                    " Move 3 words forward
2}                    " Jump 2 paragraphs forward

Editing Commands

Vim's editing power comes from composable commands: operator + motion or operator + text object.

Key Concepts

The grammar of Vim editing follows the pattern:

  • Operator + Motion: d3w (delete 3 words)
  • Operator + Text Object: ci" (change inside quotes)
  • Doubled operator: dd (delete line), yy (yank line)
ResultCombined ActionMotions/Objectsw - wordiw - inner wordaw - a wordi{ - inner bracesp - paragraphOperatorsd - deletec - changey - yankResultCombined ActionMotions/Objectsw - wordiw - inner wordaw - a wordi{ - inner bracesp - paragraphOperatorsd - deletec - changey - yank

Common Commands/Patterns

# Core operators
d       " Delete (cut)
c       " Change (delete and enter Insert mode)
y       " Yank (copy)
p       " Paste after cursor
P       " Paste before cursor
>       " Indent right
<       " Indent left
=       " Auto-indent
~       " Toggle case
gu      " Lowercase
gU      " Uppercase

# Delete operations
x       " Delete character under cursor
X       " Delete character before cursor
dd      " Delete entire line
D       " Delete to end of line
dw      " Delete word
d$      " Delete to end of line
d0      " Delete to beginning of line
dgg     " Delete to beginning of file
dG      " Delete to end of file

# Change operations
cc      " Change entire line
C       " Change to end of line
cw      " Change word
c$      " Change to end of line

# Yank operations
yy      " Yank entire line
Y       " Yank entire line (same as yy)
yw      " Yank word
y$      " Yank to end of line

# Text objects (used with operators)
iw      " Inner word
aw      " A word (includes surrounding space)
is      " Inner sentence
as      " A sentence
ip      " Inner paragraph
ap      " A paragraph
i"      " Inside double quotes
a"      " A double-quoted string
i'      " Inside single quotes
i)      " Inside parentheses
ib      " Inside parentheses (same as i))
i]      " Inside square brackets
i}      " Inside curly braces
iB      " Inside curly braces (same as i})
it      " Inside HTML/XML tag
at      " A tag (includes tags)

# Undo and redo
u       " Undo
Ctrl-r  " Redo
.       " Repeat last change

Examples

" Delete a function parameter
f,          " Find comma
dt,         " Delete till next comma
" or
di(         " Delete inside parentheses

" Change a string value
ci"         " Change inside double quotes
" Type new value
<Esc>

" Swap two lines
ddp         " Delete line, paste below

" Duplicate a line
yyp         " Yank line, paste below

" Indent a block of code
>ip         " Indent inner paragraph
" or in Visual mode
Vjj>        " Select lines, indent

" Change case of a word
gUiw        " Uppercase inner word
guaw        " Lowercase a word

" Delete to a specific character
dt)         " Delete till closing parenthesis
df)         " Delete including closing parenthesis

" Quickly fix a typo
xp          " Transpose characters (delete and paste)

Search and Replace

Powerful pattern matching and substitution capabilities for finding and modifying text.

Key Concepts

  • Search uses regular expressions by default
  • Substitution follows the pattern :[range]s/pattern/replacement/[flags]
  • Magic mode controls regex interpretation (\v for very magic, \V for very nomagic)

Common Commands/Patterns

# Basic search
/pattern        " Search forward
?pattern        " Search backward
n               " Next match (same direction)
N               " Next match (opposite direction)
*               " Search word under cursor forward
#               " Search word under cursor backward
g*              " Search partial word forward
g#              " Search partial word backward

# Search options
/pattern\c      " Case-insensitive search
/pattern\C      " Case-sensitive search
/\vpattern      " Very magic (extended regex)
/\Vpattern      " Very nomagic (literal)

# Substitution syntax
:s/old/new/     " Replace first on current line
:s/old/new/g    " Replace all on current line
:%s/old/new/g   " Replace all in file
:%s/old/new/gc  " Replace all with confirmation
:5,10s/old/new/g " Replace on lines 5-10
:'<,'>s/old/new/g " Replace in visual selection

# Substitution flags
g               " Global (all occurrences on line)
c               " Confirm each substitution
i               " Case-insensitive
I               " Case-sensitive
n               " Count matches without replacing
e               " No error if pattern not found

# Special replacements
&               " The matched pattern
\0              " The entire match
\1, \2, etc.    " Captured groups
\r              " Newline in replacement
\t              " Tab in replacement
\u              " Next character uppercase
\l              " Next character lowercase
\U              " Following characters uppercase
\L              " Following characters lowercase
\E              " End case modification

# Global command
:g/pattern/d    " Delete all lines matching pattern
:g/pattern/cmd  " Run cmd on matching lines
:v/pattern/d    " Delete lines NOT matching pattern

Examples

" Replace all occurrences in file
:%s/color/colour/g

" Replace with confirmation
:%s/foo/bar/gc
" y = yes, n = no, a = all, q = quit, l = last

" Case-insensitive replace
:%s/error/warning/gi

" Delete blank lines
:g/^$/d

" Delete lines containing pattern
:g/DEBUG/d

" Move lines containing pattern to end of file
:g/TODO/m$

" Use captured groups
:%s/\(\w\+\):\(\w\+\)/\2:\1/g  " Swap word:word

" Very magic mode for cleaner regex
:%s/\v(\w+):(\w+)/\2:\1/g      " Same as above

" Replace in visual selection only
'<,'>s/old/new/g

" Search and replace with newlines
:%s/; /;\r/g    " Put semicolons on their own line

" Double-space a file
:%s/$/\r/

" Remove trailing whitespace
:%s/\s\+$//e

" Convert tabs to spaces
:%s/\t/    /g

" Comment out lines matching pattern
:g/pattern/s/^/# /

Buffers, Windows, and Tabs

Vim provides three levels of workspace organisation: buffers (files), windows (viewports), and tabs (layouts).

Key Concepts

  • Buffer: An in-memory representation of a file
  • Window: A viewport into a buffer (split view)
  • Tab: A collection of windows (workspace)
Hidden BuffersBuffer CBuffer DTab 2Window 3Buffer ATab 1Window 2Buffer BWindow 1Buffer AHidden BuffersBuffer CBuffer DTab 2Window 3Buffer ATab 1Window 2Buffer BWindow 1Buffer A

Common Commands/Patterns

# Buffer commands
:e filename     " Edit file in new buffer
:enew           " Create new empty buffer
:ls             " List all buffers
:buffers        " List all buffers (same as :ls)
:b name         " Switch to buffer by name/number
:bn             " Next buffer
:bp             " Previous buffer
:bd             " Delete (close) buffer
:bd!            " Force delete buffer (discard changes)
:ball           " Open all buffers in windows
:bufdo cmd      " Execute cmd in all buffers

# Window commands
:sp [file]      " Horizontal split
:vsp [file]     " Vertical split
:new            " New window with empty buffer
:vnew           " New vertical window with empty buffer
Ctrl-w s        " Horizontal split
Ctrl-w v        " Vertical split
Ctrl-w n        " New window with empty buffer
Ctrl-w c        " Close window
Ctrl-w q        " Quit window
Ctrl-w o        " Close all other windows

# Window navigation
Ctrl-w h        " Move to left window
Ctrl-w j        " Move to window below
Ctrl-w k        " Move to window above
Ctrl-w l        " Move to right window
Ctrl-w w        " Cycle through windows
Ctrl-w p        " Previous window

# Window resizing
Ctrl-w =        " Equalise window sizes
Ctrl-w _        " Maximise height
Ctrl-w |        " Maximise width
Ctrl-w +        " Increase height
Ctrl-w -        " Decrease height
Ctrl-w >        " Increase width
Ctrl-w <        " Decrease width
:resize 20      " Set height to 20 lines
:vertical resize 80 " Set width to 80 columns

# Window moving
Ctrl-w r        " Rotate windows downward
Ctrl-w R        " Rotate windows upward
Ctrl-w x        " Exchange with next window
Ctrl-w H        " Move window to far left
Ctrl-w J        " Move window to bottom
Ctrl-w K        " Move window to top
Ctrl-w L        " Move window to far right

# Tab commands
:tabnew [file]  " New tab
:tabc           " Close tab
:tabo           " Close all other tabs
:tabn           " Next tab
:tabp           " Previous tab
gt              " Next tab
gT              " Previous tab
3gt             " Go to tab 3
:tabm 0         " Move tab to position 0
:tabdo cmd      " Execute cmd in all tabs

Examples

" Open multiple files and navigate
vim file1.txt file2.txt file3.txt
:bn             " Switch to file2.txt
:b file3        " Switch to file3.txt
:ls             " See all open buffers

" Compare two files side by side
:e file1.txt
:vsp file2.txt
Ctrl-w l        " Move to right window

" Edit code with reference file
:e main.py
:sp config.py   " Open config above for reference
Ctrl-w k        " Look at config
Ctrl-w j        " Return to main

" Organise work with tabs
:tabnew         " Create workspace tab
:e src/app.py
:vsp tests/test_app.py
gt              " Switch to next tab

" Apply change across all buffers
:bufdo %s/old/new/ge | update

" Close all buffers except current
:%bd|e#

" Open file in existing buffer
:e!             " Reload current file (discard changes)

Macros and Registers

Macros record and replay keystrokes; registers store text and macros for later use.

Key Concepts

  • Registers are storage locations named a-z, 0-9, and special characters
  • Macros are sequences of commands stored in registers
  • Registers persist across Vim sessions (stored in viminfo)
Register Purpose
"a-z Named registers (user storage)
"A-Z Append to named register
"0 Last yank
"1-9 Delete history (rotating)
"" Unnamed (default) register
"- Small delete register
". Last inserted text
": Last command-line command
"/ Last search pattern
"* System clipboard (X11 primary)
"+ System clipboard (X11 clipboard)
"_ Black hole register
"% Current filename
"# Alternate filename

Common Commands/Patterns

# Recording macros
qa              " Start recording macro to register 'a'
<commands>      " Perform your actions
q               " Stop recording
@a              " Execute macro 'a'
@@              " Repeat last executed macro
5@a             " Execute macro 'a' 5 times
:5,10normal @a  " Execute on lines 5-10

# Register operations
"ayy            " Yank line to register 'a'
"Ayy            " Append line to register 'a'
"ap             " Paste from register 'a'
"adiw           " Delete word into register 'a'

# Viewing registers
:reg            " Show all registers
:reg a          " Show register 'a'
:reg ab         " Show registers 'a' and 'b'

# Special registers
"*p             " Paste from system clipboard
"+y             " Yank to system clipboard
"_dd            " Delete without saving to register
".p             " Paste last inserted text
"0p             " Paste last yank (not delete)
":p             " Paste last command

# Insert mode register access
Ctrl-r a        " Insert contents of register 'a'
Ctrl-r =        " Expression register (calculator)
Ctrl-r /        " Insert last search pattern
Ctrl-r %        " Insert current filename

Examples

" Macro to add quotes around a word
qa              " Start recording to 'a'
ciw"<Ctrl-r>""  " Change word, add quotes, paste
<Esc>           " Return to normal
q               " Stop recording
@a              " Apply to another word

" Macro to format a list item
qa              " Start recording
0               " Go to line start
i* <Esc>        " Add bullet
j               " Move to next line
q               " Stop recording
10@a            " Apply to 10 more lines

" Macro with search
qa              " Start recording
/TODO<CR>       " Find TODO
dd              " Delete the line
q               " Stop recording
100@a           " Remove all TODOs (repeat 100 times)

" Append to macro to fix mistakes
qA              " Append to existing macro 'a'
<fix commands>
q

" Copy between registers
:let @b = @a    " Copy macro 'a' to 'b'

" Edit a macro
:let @a = '<Ctrl-r>a'  " Puts content in command line to edit

" Macro for adding log statements
qa
yiw             " Yank word (variable name)
oconsole.log('<Ctrl-r>":', <Ctrl-r>");<Esc>
q
" Now @a adds logging for any variable

" Using expression register
"=5*42<CR>p     " Insert result of 5*42

" In insert mode
<Ctrl-r>=system('date')<CR>  " Insert current date

" Numbered registers (delete history)
"1p             " Paste most recent delete
.               " Paste next oldest
.               " Paste next oldest

Quick Reference

Mode Switching

Command Action
i / a Insert before/after cursor
I / A Insert at start/end of line
o / O New line below/above
v / V / Ctrl-v Visual character/line/block
Esc Return to Normal mode

Essential Navigation

Command Action
h j k l Left, down, up, right
w / b Next/previous word
0 / $ Line start/end
gg / G File start/end
Ctrl-d / Ctrl-u Half page down/up
/{pattern} Search forward
n / N Next/previous match

Core Editing

Command Action
dd / yy Delete/yank line
p / P Paste after/before
u / Ctrl-r Undo/redo
. Repeat last change
ciw / diw Change/delete inner word
ci" / di" Change/delete inside quotes

Buffers, Windows, Tabs

Command Action
:e file Edit file
:w / :q Save/quit
:ls / :bn / :bp List/next/previous buffer
Ctrl-w s / Ctrl-w v Horizontal/vertical split
Ctrl-w h/j/k/l Navigate windows
gt / gT Next/previous tab

Search and Replace

Command Action
:%s/old/new/g Replace all in file
:%s/old/new/gc Replace with confirmation
:g/pattern/d Delete matching lines
* / # Search word forward/backward

Macros and Registers

Command Action
qa ... q Record macro to 'a'
@a / @@ Play macro / repeat last
"ayy / "ap Yank to / paste from 'a'
"+y / "+p System clipboard yank/paste
:reg View registers

Common Issues and Solutions

Cannot exit Vim

Problem: Stuck in Vim, don't know how to quit.

Solution:

<Esc>           " Ensure you're in Normal mode
:q              " Quit (fails if unsaved changes)
:q!             " Force quit without saving
:wq             " Save and quit
ZZ              " Save and quit (shortcut)
ZQ              " Quit without saving (shortcut)

Pasted text is incorrectly indented

Problem: Pasting from clipboard adds unwanted indentation.

Solution:

:set paste      " Enable paste mode
p               " Paste your content
:set nopaste    " Disable paste mode

" Or use the paste toggle
:set pastetoggle=<F2>
" Then press F2 before pasting

Search is case-sensitive when you want case-insensitive

Problem: Search doesn't find matches with different capitalisation.

Solution:

/pattern\c      " Case-insensitive search
:set ignorecase " Always ignore case
:set smartcase  " Ignore case unless pattern has uppercase

Cannot delete or yank to system clipboard

Problem: Yanked text not available outside Vim.

Solution:

" Check clipboard support
:echo has('clipboard')

" Use clipboard registers
"+y             " Yank to system clipboard
"+p             " Paste from system clipboard
"*y             " Yank to primary selection (Linux)

" Configure default
:set clipboard=unnamedplus

Macro stops before completing all iterations

Problem: Macro executed with count stops early.

Solution: Ensure macro doesn't fail. Common issues:

  • Search pattern not found
  • Movement goes past file boundary
  • Command fails on certain lines
" Make macro more robust
:set nowrapscan  " Don't wrap search
" Or add error suppression to macro

Replace affects wrong occurrences

Problem: Substitute changes unintended matches.

Solution:

" Use word boundaries
:%s/\<old\>/new/g    " Match whole word only

" Use confirmation
:%s/old/new/gc       " Confirm each replacement

" Limit scope
:5,20s/old/new/g     " Only lines 5-20
:'<,'>s/old/new/g    " Only visual selection

File opens with ^M characters

Problem: Windows line endings showing as ^M.

Solution:

" Convert to Unix line endings
:set fileformat=unix
:w

" Remove ^M characters
:%s/\r//g

" Or use dos2unix externally
:!dos2unix %

Changes lost when switching buffers

Problem: Vim won't let you switch buffers with unsaved changes.

Solution:

:set hidden         " Allow hidden buffers with changes
:set autowrite      " Auto-save before switching
:wa                 " Write all changed buffers

Related Topics

These topics complement Vim and would enhance your command-line workflow:

  1. Tmux - Terminal multiplexer for session management, pairs excellently with Vim for a complete terminal-based development environment
  2. Bash/zsh - Shell scripting and customisation; Vim's command mode uses similar patterns
  3. git - Version control; Vim has excellent git integration plugins and serves as the default git editor
  4. Regular Expressions - Deeper regex knowledge enhances Vim's search and substitution capabilities
  5. Linux CLI - Command-line tools that integrate with Vim (grep, sed, awk)
  6. Neovim/Vim Plugins - Extend Vim's capabilities with plugin managers and popular plugins (vim-plug, coc.nvim, telescope)