How do I split a complex Vim macro into reusable subroutines?
Answer
Record worker macro in @b, call it from @a with @b
Explanation
Complex macros are hard to debug and maintain when crammed into a single register. By splitting work into a worker macro and a driver macro, you can test each part independently, reuse the worker across different contexts, and modify behavior without re-recording everything from scratch.
How it works
- Record the core transformation in one register (e.g.,
@b) — this is the "worker" - Record the orchestration logic in a second register (e.g.,
@a) — this calls@band handles positioning/looping - Inside macro
@a, type@bto invoke the worker at the right moment - Any register can call any other register with
@{register}
Example
Suppose you want to wrap each CSV field on a line in quotes. First record the worker in @b — it quotes one word:
qb f, a"<Esc>F,i"<Esc>q
Then record the driver in @a — it runs @b repeatedly across the line:
qa 0@b 3@b j q
Now @a processes one full line. Run 10@a to process 10 lines.
Tips
- Test
@balone on a single item before building@aaround it - Changing
@b(via:let @b = ...) affects all callers immediately - Worker macros pair well with
:normal @bacross a range — run the worker on every line matching a pattern::g/pattern/normal @b - You can chain three or more registers:
@acalls@bwhich calls@c - Keep worker macros short and single-purpose; put loop control exclusively in the driver