How do I run a macro a dynamically computed number of times or interleave it with other commands?
Answer
:for i in range(1,10) | execute "normal @q" | endfor
Explanation
Using a Vimscript :for loop with execute "normal @q" lets you run a macro with a dynamically computed iteration count and interleave other Ex commands between invocations. Unlike 10@q, the count can be any Vimscript expression, and you can branch or act on each iteration.
How it works
:for i in range(1, N)iterates N times (Vimscriptrange()is exclusive of the stop value, sorange(1,11)gives 1–10)execute "normal @q"runs macro@qas if typed in normal mode- Multiple commands are separated by
|on a single Ex command line execute "normal! @q"(with!) uses no remapping, which can matter inside complex macros
Example
Apply macro @q once for every line in the file:
:for i in range(1, line('$')) | execute "normal @q" | endfor
Apply @q only on even-numbered iterations:
:for i in range(1, 20)
: if i % 2 == 0 | execute "normal @q" | endif
:endfor
Run @q and advance 5 lines between each invocation:
:for i in range(1, 10) | execute "normal @q5j" | endfor
Tips
- The standard
{count}@qis simpler for fixed counts, but it stops entirely if any iteration errors; the:forapproach lets you add error handling with:try/:catch - Combine with
:g/pattern/execute "normal @q"to apply the macro only on matching lines - Use
i(the loop variable) insideexecuteto build commands that vary per iteration:execute "normal " . i . "@q"