Monday, April 23, 2012

Undo & Continue Confirmed Substitution

Janni on #vim asks:

When using substitution (:s) with the [c] flag one can use several keys to
confirm/skip concrete substitutions. I'd really like to get the additional
option to undo the last substitution.  (without exiting the substitution
process as a whole)


Here's how I would handle that situation:

For demonstration purposes, let's replace "e" with "z".

We have to start on the first line, so type   gg

The following command operates on all lines from the cursor to the end of the
file which contain an "e":

:.,$g/e/s//z/gc

The /c on the :substitute command there prompts us at every replace position. See :help :s_flags for an explanation of the interactive options.

If you want to undo the previous one, press   ctrl-c   to cancel the :global
command and then press   u   to undo and   j   to move down a line (skipping
over the line you just undid so as not to be asked about it again). Then re-run
the   :.,$g/e/s//z/gc   command. The easiest way to do that is to press
:<up><enter>

It'd be nice to have an extra   u   option in the interactive confirmed
substitution command to undo the last replacement. Until then, enjoy.

Update:

The ever  vigilant Raimondi caught me with my pants down again. It turns out, we don't need the extra :g// at all here. A simple:

:.,$s/e/z/gc

is sufficient. It has exactly the same runtime mechanics as the method described above — that is, use ctrl-c to cancel the operation midway, u to undo changes and then :<up><enter> to recommence the substitute from the current line onwards. Thanks for keeping me honest, Raimondi. <3

Your gem, my rock:

Sir Raimondi followed up with another eloquent query:

y u no @: bairui?!

Ah... good question. Ostensibly, I didn't show @: because I rarely use it myself. For my needs, :<up><cr> is in the muscle memory... Besides, @: is not necessarily easier for me to reach. Also, it gives me a chance to eye-ball it before accidentally re-running the wrong command. My supply of brown underwear is limited so it behooves me to be a little cautious around my :ex.

But yes, @: and then subsequent @@ is faster if you know you have to re-run an :ex command many times, as is the case here... but if you're having to do that a lot manually... I smell fishies... :-) Of course, I just polluted your wading pond with a load of carp by suggesting you do exactly that above — what can I say? When you know the rules, you can break the rules?   :-p   Love as always, R.

2 comments:

  1. :%s#g/e/s/#s/e#g unless I'm missing something there...

    ReplyDelete
  2. the empty pattern in s// re-uses the pattern in the g//

    ReplyDelete