2

Often I would record a macro and run it till end of file like 200@q. However, there may be a few lines/instances at the bottom I don't want to run the macro on (like 5 lines). Pressing u would undo all 200 executions, redoing it takes some time, and I don't want to have to count exactly how many instances I have to use the macro on. (or do what I currently do, binary-search like run-undo)

I'd like to be able to do something like 500@q and then 5 <undo_macro> which runs till EOF & just undoes the last 5 lines/instances.

How can I do such macro-undoing?

3

Typically, Vim considers a mapping or a recorded macro as a single change, so if you press u to undo it, it will undo all of it. There exists the possibility to break an undo-sequence into smaller parts, so that you can undo each part of it independently.

For that, the generic way is to enter CTRLGu in Insert mode. (See :h i_CTRL-G_u). So simply add CTRLGu if you are in insert mode while recording your macro and it should work. However, this requires to enter insert mode and leave it again if you are not currently in insert mode (and sometimes even that does not work, but I forgot when).

A little known trick however is to use the ex command :let &ul=&ul to assign the current number of undolevels to the undolevels option again. Besides an no-op, this also breaks the undo sequence and works even when running a scripted vim (this is widely used in the Vim test suite). So it might be easier to append to your recorded macro this ex command:

:let @A=":let &ul=&ul\n"

(assuming you are recording into register a)

Note, that this might make executing your macro a bit slower.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.