Undo in Vi and its successors

So vi only has one level of undo, which is simply no longer fit for the times we live in now, and also wholly unnecessary given even the least powerful devices that might need to run vi probably have more than enough resources to give at least a few more levels of undo. What I didn’t know, however, is that vi’s limited undo behaviour is actually part of POSIX, and for full compliance, you’re going to need it. As Chris Siebenmann notes, vim and its derivatives ignore this POSIX requirement and implement multiple levels of undo in the obviously correct way.

What about nvi, the default on the BSD variants? I didn’t know this, but it has a convoluted workaround to both maintain POSIX compatibility and offer multiple levels of undo, and it’s definitely something.

Nvi has opted to remain POSIX compliant and operate in the traditional vi way, while still supporting multi-level undo. To get multi-level undo in nvi, you extend the first ‘u’ with ‘.’ commands, so ‘u..’ undoes the most recent three changes. The ‘u’ command can be extended with ‘.’ in either of its modes (undo’ing or redo’ing), so ‘u..u..’ is a no-op. The ‘.’ operation doesn’t appear to take a count in nvi, so there is no way to do multiple undos (or redos) in one action; you have to step through them by hand. I’m not sure how nvi reacts if you want do things like move your cursor position during an undo or redo sequence (my limited testing suggests that it can perturb the sequence, so that ‘.’ now doesn’t continue undoing or redoing the way vim will continue if you use ‘u’ or Ctrl-r again).

↫ Chris Siebenmann

Siebenmann lists a few other implementations and how they work with undo, and it’s interesting to see how all of them try to solve the problem in slightly different ways.

Leave a Reply