Macros

Vim Intermediate/Advanced

Chapter 1 — Macros

The Problem Macros Solve

You've likely already used . (the dot command) to repeat your last single change — a genuinely useful shortcut, but limited to one edit at a time. Real repetitive work is rarely that simple: reformatting fifty lines of a CSV, converting a list of names into function calls, adding the same three-line boilerplate above every function in a file. Each of those is a whole sequence of keystrokes you'd otherwise have to repeat by hand, once per line, for however many lines the task touches.

A macro is a recorded sequence of any keystrokes — motions, edits, searches, even other commands — stored in a register (Chapter 2) and replayable on demand, as many times as you like. Where the dot command repeats one action, a macro repeats anything you can type.

Recording a Macro

q followed by a register letter starts recording; pressing q again stops it. Everything typed in between — in any mode — becomes part of the macro.

qa                # start recording into register 'a'
0i"<Esc>A",<Esc>  # the actual edit: wrap the line in quotes, add a trailing comma
j                 # move down to the next line, ready for the macro's next run
q                 # stop recording
What gets recorded is literal keystrokes, not intent. Vim has no idea "you meant to quote the current line" — it only knows you pressed 0, then i, then ", then Esc, and so on, in that exact order. This is exactly why the j at the end of the example above matters: without it, replaying the macro would repeat the edit on the same line every time rather than advancing.

Why register a-z, and not 0-9?

Macros are stored in the exact same named registers (Chapter 2) used for yanked and deleted text — there's no separate "macro register" type. Recording into register a with qa...q and yanking a word into register a with "ayiw both write to the identical storage slot; whichever happened most recently is what's there now. Pick a register you're not actively using for something else during the same editing session.

Playing Back a Macro

@a          # play macro 'a' once
@@          # repeat the LAST macro played — regardless of which register it came from
5@a         # play macro 'a' five times in a row

@@ is worth building into muscle memory early — after playing @a once to confirm it worked correctly, @@ lets you keep repeating it without retyping the register letter each time.

Applying a Macro Across Many Lines

A large count is the simplest way to apply a macro repeatedly down a file:

100@a       # attempt to play macro 'a' up to 100 times
A macro stops naturally when it hits an error. If macro a ends with j (move down a line) and you're already on the last line of the file, that j fails — and a failed command inside a macro stops the whole macro immediately, rather than continuing past it. In practice, this means 100@a on a 23-line file safely stops after line 23 instead of erroring out or corrupting later lines — you can specify a count far larger than you actually need without worrying about overrunning the file.

Applying a macro to a Visual selection

When you want a macro applied to a specific range rather than "the rest of the file," select the target lines in Visual Line mode first, then invoke the macro via :normal:

V            # enter Visual Line mode
jjjj         # extend the selection down 4 more lines (5 lines total)
:normal @a  # Vim auto-fills this as :'<,'>normal @a — runs the macro once per selected line

:normal executes the given keystrokes as if typed in Normal mode, once for every line in the given range — here, the visually selected range. This sidesteps the "will it stop in time?" question entirely: the macro only ever runs across the lines you explicitly selected.

Always test on one line before scaling up. Whether you're about to run a large count or a :normal range, play the macro once with a plain @a first and visually confirm the result is correct. A macro that silently does the wrong thing (a mistyped keystroke, a search that doesn't match the way you expected) will happily repeat that mistake across every remaining line just as reliably as it would the correct edit — mass-applying a bug is exactly as easy as mass-applying a fix.

Editing a Macro — Since It's Just a Register

Because a macro is stored in an ordinary register, you're not locked into re-recording from scratch if you spot a mistake. You can paste it into the buffer as text, fix the typo, and yank it back:

Workflow — fixing a mistyped macro without re-recording

1 "ap Paste register a's contents into the buffer, on its own line, as plain editable text.
2 (edit the line) The macro's keystrokes are now literal characters — fix the mistyped one directly, same as editing any other text.
3 "ay$ Yank from the cursor to the end of the line back into register a, overwriting the old (broken) version.
4 dd (or u) Delete the now-unneeded pasted line (or undo the paste) — the fixed macro already lives safely back in register a.
Special keys appear as control characters when pasted. An <Esc> recorded inside a macro shows up as ^[ when pasted as text (and a literal Enter as ^M) — these are the actual character, not a two-character sequence, so editing around them works the same as any other single character. It looks unusual the first time you see it, but it pastes and re-yanks correctly regardless.

A Worked Example

Turning a plain list of names into a quoted, comma-terminated list — the kind of transform that comes up constantly when reshaping data for code:

# Before:
John Smith
Jane Doe
Alex Chen

# After:
"John Smith",
"Jane Doe",
"Alex Chen",
# With the cursor on the first line:
qa              # start recording into 'a'
I"<Esc>       # insert a quote at the start of the line
A",<Esc>      # append a closing quote and comma at the end of the line
j               # move to the next line
q               # stop recording

2@a             # apply to the remaining 2 lines (test with @a first, per this chapter's warn-box, then @@ or a count)

Commands Introduced in This Chapter

Chapter 1 — Command Reference

Recording
q{register}Start recording keystrokes into the given register
qStop recording (while already recording)
Playback
@{register}Play the macro stored in the given register, once
@@Repeat the last macro played, regardless of its register
{count}@{register}Play a macro up to {count} times, stopping early on the first error
Applying across a range
V (select lines) then :normal @aRun a macro once per line in a Visual selection
Editing a recorded macro
"{register}pPaste a macro's contents as editable text
"{register}y$Yank the edited line back into the register as the corrected macro