Friday, June 12, 2009

Recursive Macros

A friend at work pointed out to me yesterday that he had accidentally written a recursive macro in Vim. I had never thought about the fact that this was possible, but I'd imagine there could be some potential usefulness for these somewhere. As a trivial (and useless) example, here's a recursive macro to move the cursor to the end of the current line one step at a time: qal@aq

Edit: A little research has shown that this is an excellent way to repeat a macro to the end of the file. Say that you have a file containing one number per line from top to bottom:

123
234
345
456

Put the cursor on the first line and type the following:

qaq (clears register "a" of any previous macros)
qa<ctrl-a><enter>@aq

Now type @a once more, and the macro will run to the bottom of the file incrementing the value on each line by one leaving you with the following:

124
235
346
457

7 comments:

${spencer} said...

took me a while to get my head around that. not sure if i'll ever use it, but nice to know. cheers

David said...

haha cool, great tip thanks. I can't see any use for it at the moment except for how you used it to process a whole file. But fun tip.

Igor Almeida said...

Being recursive with no stop condition, I'd guess it would just continue to run ad infinitum, but vim seems to understand this and somehow halts the loop.

Christopher Suter said...

@igor vim macros will die if any of their actions fail -- for example, searching for a term which does not appear in the current buffer. Thus, for the post example, when the cursor can no longer go to the next char or the next line (whichever it was...), the macro will fail and the recursion will end.

Igor Almeida said...

Interesting, I didn't know that.
Thank you, Christopher

Linus said...

Any idea how to add a recursive macro into the ~/.vimrc file (as a hotkey)? I tried "nmap <leader>ni qa<C-a>j@aq" but for some reason it interprets the "@a" incorrectly and leaves the macro open (the second "q" does not get caught). I tried nnoremap, but that doesn't work either. I don't want to use a macro storage plugin because that's overkill.

Is this a vim bug? I'm using vim version 7.2.65

Tim D said...

Thanks for the tip!

If you're using the yankring plugin, it will query the user for the register name each time. I need to see if there's a way to silence this for macros.