Every Vim user builds a personal toolkit over time. The commands below are ones I kept bumping into — not in tutorials, but in the middle of actual work when the usual approach felt like one step too many. Each one solves a real friction point rather than just being clever for its own sake.
1) Recursive macros that stop themselves
Why it matters
When you record a macro to process N items, you usually need to know N in advance. Most people use a large count like 99@q and hope that's enough. A recursive macro is cleaner: it calls itself at the end of its body and stops automatically the moment any command in the sequence fails — no counting required.
qqq
qq{your commands}@qq
@q
The first line (qqq) clears register q so the embedded @q at the end of the recording is a harmless no-op rather than invoking a stale old macro. Then you record your macro and include @q as the final keystroke. Once recorded, @q starts the loop.
Real scenario
You have a list of lines where each one needs the first word removed. You don't know how many lines there are. Record qqdw0j@qq, then hit @q. The macro deletes the first word, moves to column 0, steps down one line, and recurses — until j fails on the last line and the whole chain stops.
Caveat
If the macro gets stuck in an infinite loop, <C-c> interrupts it. Also: if a command fails midway on a line rather than at the end of the file, the macro will stop early. Make sure your "stop condition" is the one thing that naturally fails when the work is done.
2) Pattern-relative offsets in Ex ranges
Why it matters
Ex command ranges usually use line numbers or marks, but Vim also lets you write ranges in terms of search patterns with numeric offsets. This means you can operate on "the three lines after the TODO comment" or "everything between two section markers" without knowing any line numbers at all.
:/pattern/+N,/other-pattern/-N delete
The /pattern/+1 form says "the line one below the next match of this pattern." The -1 form says "the line one above." You can use these addresses with any Ex command that takes a range: :delete, :yank, :move, :copy, :substitute, :normal, and so on.
Real scenario
A config file has sections delimited by # BEGIN and # END comments, and you need to delete everything between them (not including the markers themselves):
:/# BEGIN/+1,/# END/-1delete
That's a complete command. No line number lookup, no visual selection. Works regardless of where in the file the block lives.
Caveat
If the search pattern doesn't exist in the buffer, Vim will error out. When scripting this kind of range, wrap the command in :silent! or guard with a pattern check first. Also remember that /pattern/ searches forward from the cursor — position matters when a pattern appears multiple times.
3) Opening the command-line window mid-command
Why it matters
Vim's command-line window (q: from Normal mode) is great for editing and re-running previous commands. Less known is that you can open it while you're already typing a command — press <C-f> in the middle of your :s substitution and Vim drops you into the command-line window with your half-typed command loaded and ready for full Vim editing.
<C-f> (press while in : / ? mode)
This works from any command-line mode: :, /, ?, or !. The in-progress command appears at the bottom of the window, and you can use any Normal-mode motions to fix it before pressing <CR> to execute.
Real scenario
You're typing a complicated substitution:
:%s/\v(class|module)\s+\zs\w+/
You realize you got the regex wrong two groups back. Instead of <C-b> and arrow keys, press <C-f>. The command opens in an editable buffer. Use F( to jump to the paren, ci( to fix it, then <CR> on the line to run it.
Caveat
q: from Normal mode also opens the command-line window, but it only shows history — it cannot capture what you were currently typing. <C-f> is specifically for the mid-input case. Close the window without running with :q or <C-c>.
4) The '^ mark: return to the last insert position
Why it matters
Vim automatically updates the ^ mark every time you leave Insert mode. Pressing '^ in Normal mode jumps back to the exact position where your cursor was when you hit <Esc>. Unlike gi — which jumps there and immediately re-enters Insert mode — '^ is a plain mark jump: you arrive, look around, and decide when to start editing again.
'^
Real scenario
You're editing a function, escape out to check a related block above, then use /search or % to explore a bit. When you're ready to return, '^ brings you straight back to column and line — no searching, no <C-o> chain. Then press a or i when you're actually ready to type.
Caveat
If gi already fits your workflow — jump back and start typing — there's no reason to switch. '^ is the right choice when you want to inspect the position first, or when you want to use an operator there rather than enter Insert mode. The mark is also buffer-global: if you switched files, '^ will switch back to the other buffer.
5) gP — paste before the cursor, land after it
Why it matters
The standard P pastes text before the cursor and leaves the cursor sitting on the first character of what was just inserted. gP pastes in the same position but moves the cursor to after the inserted text. That might sound minor, but when you're assembling content from multiple pastes or continuing to type immediately after, it eliminates the manual $ or e move you'd otherwise need.
gP
The lowercase gp is the after-cursor equivalent of p — same behavior, cursor ends up after the paste.
Real scenario
You're building a line by pasting three named registers in sequence. With "agP"bgP"cgP, each paste leaves your cursor positioned for the next, and you end up after all three pieces without touching a motion key in between.
Caveat
gP with a count (3gP) pastes three copies in a row and leaves the cursor after all three, not after just the first. This is intentional and usually what you want, but it's worth knowing before you use it inside a macro.
Wrap-up
These five commands live in different areas of Vim — macros, Ex ranges, command-line editing, marks, and paste operations — but they share a common thread: each one removes a step that you'd otherwise do manually. Recursive macros eliminate counting. Pattern offsets eliminate line number lookups. <C-f> eliminates awkward command-line navigation. '^ eliminates refinding your position. gP eliminates cursor repositioning after paste.
If you want more practical Vim tricks explained at this level, I publish them at https://vimtricks.wiki.
What Vim workflow still has a step you wish you could skip?
Top comments (0)