How do I build a macro programmatically using Vimscript instead of recording it?
Answer
:call setreg('q', keys, 'c')
Explanation
The setreg() function writes any string directly into a named register, letting you construct macro keystrokes from Vimscript expressions rather than live recording. This is invaluable when the macro content needs to include computed values — file paths, line numbers, dynamic patterns — that cannot be known at record time.
How it works
setreg(register, content, type)sets the named register tocontentregisteris a single character ('q','a', etc.)contentis a string of keystrokes in the same notation Vim stores internally: use\<Esc>,\<CR>, etc., or the literal control characters via"\x1b"typemust be'c'(characterwise) for the register to behave as a macro; linewise ('l') or blockwise ('b') registers do not work as macros- After calling
setreg(), run the macro with@qas normal
Example
Append the current line number to each line in a range, without hardcoding the number:
" Build a macro that appends " -- line N" to the current line
let lnum = line('.')
call setreg('q', 'A -- line ' . lnum . "\<Esc>", 'c')
@q
Or build a find-and-replace macro using a computed pattern:
let word = expand('<cword>')
call setreg('q', ':s/\<' . word . '\>/NEW_NAME/g\<CR>', 'c')
Then @q runs the substitution immediately, and @@ repeats it on demand.
Tips
- Inspect the result with
:reg qbefore running to verify the content looks right - To include literal special keys, use
"\<Esc>"or\"\<CR>\"in the expression; these are the same escape sequences Vim stores internally - Combine with
:argdoor:bufdoplusnorm @qto replay the programmatic macro across many files