15

Sometimes I'm on a system without Vim, and use the default nvi (BSD systems) or the original vi (Arch Linux).

There are quite a few differences, but the largest annoyance is that I can undo only my last operation. Pressing u the second time works are a "redo".

Is there some way to get this working?

3 Answers 3

19

From nvi(1):

 u       Undo the last change made to the file.  If repeated, the u command
         alternates between these two states.  The . command, when used
         immediately after u, causes the change log to be rolled forward or
         backward, depending on the action of the u command.

So press u, and then keep pressing . for more undo; If you press u again, it will 'reverse' direction and pressing . will be a redo.

I never knew about this until yesterday; and thought it was somehow a new feature, but it seems like it has worked like this since at least nvi 1.79 from 1996.

This doesn't work in the original vi; where the undo is documented as:

   u      Undoes the last change made to the current buffer.  If repeated,
          will alternate  between  these  two  states,  thus  is  its  own
          inverse.  When  used after an insert which inserted text on more
          than one line, the lines are saved in the numeric named  buffers
          (3.5).

Which is really a complicated way of saying that pressing u again will redo your changes.

Which is also what Vim's :help undo says (and why I assumed it also wouldn't work in nvi):

 u                       Undo [count] changes.  {Vi: only one level}
0
1

The closest thing the original vi has to multiple undo (aside from U which can revert multiple changes within a single line) is the numbered registers, which hold the nine most recent changes or deletions.

If you put from a numbered register, subsequent dot commands will increment that register when it repeats the command.

E.g. with the following text, with the cursor line indicated with >,

  aaaa
> bbbb
  cccc
  dddd
  eeee

the command dd.. will result in:

  aaaa
> eeee

If you then type "1P, vi will put the most recent deletion from register "1:

  aaaa
> dddd
  eeee

Hitting . will put the contents of the next most recent register, by doing "2P, and hitting . again will put the contents of register "3.

So, in short, "P.. will put back all the text you deleted, leaving you with

  aaaa
> bbbb
  cccc
  dddd
  eeee

Not brilliant, but better than nothing! More usefully you can use it at the beginning or end of the buffer to quickly inspect what's in your numbered registers. Then you can easily delete what you don't need.

It's documented in vim under :help redo-register.

-1

Using the original vi, hit [n]u to go back n steps. To progressively go back step by step...

  • hit [n]u to go back n steps
  • then hit [n]u to redo n steps
  • then hit [n+1]u to go back [n+1] steps
  • etc
2
  • 1
    I have something close to the original vi, and it doesn't seem to go back n steps.
    – muru
    Apr 18, 2016 at 19:49
  • Agreed. Original Vi can revert only a single change with u, or restore a single line to how it was before you started editing it with U.
    – Antony
    Dec 26, 2016 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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