2010-11-15

undo

One of the advantages that text-editors have over daily life is the ease of undoing things. Emacs in particular has a powerful undo-system to return to the previous state of things.

Undo can be activated by pressing C-x u or C-_; if you are more comfortable with using C-z for undo (as is the standard in many non-Emacs environments), you can of course add that key binding as well, by putting in your .emacs:

(global-set-key (kbd "C-z") 'undo)

This overrides the default of C-z triggering suspend-frame, which is not a great loss for most people.

Emacs-undo has some nice features - for example, if you have selected some text ('marked a region'), the undo operation only applies to that area. At the same time, however, the undo-model can be confusing: in emacs, undo is treated like any other command, which means that undo can be applied even to… undo, which is different from what most other editors do. Let me give an example – if it's confusing or tedious then, well, that's what it is…

Suppose I type

hello
world

now I press C-_, and I get

hello

Now I type foo

hello
foo

And press C-_ C-_; and I get back:

hello
world

This is because we're 'undoing the undo' of adding the word 'world', and thus, it reappears! When you try this in most other editors, it would result in

hello

because those editors completely forget about 'world' after it is undone.

So, emacs' model is strictly more powerful - but some (many? )people find it a bit confusing, esp. when a series of 'undos' is interrupted by a 'do'.

If you prefer the model that many other editors use, you might be interested in redo-mode, in particular in RedoPlus. Using that package, undo (or rather, redo) follows a different model. In that model, redo is 'special': it's not registered as a buffer change, and as such it's conceptually different from the redo=undo-undo model that emacs uses by default. As seen above, you actually lose some information in the process.

Yet another way to tackle the undo-problem is implemented by UndoTree: the states of your buffer are seen as nodes in a tree, and you can freely move to specific nodes. UndoTree is as powerful as the emacs system, yet easier to understand. It can even visualize the tree of changes - and you can then by clicking on a node go back to the corresponding buffer state.

Now, when using UndoTree, let's look at our example again:

We started with:

hello
world

then did C-_ (which removed 'world') and typed 'foo' to get:

hello
foo

Now press C-u again, and 'foo' disappear. Now we press C-x u (undo-tree-visualize) and we get a buffer with:

  |
  o
  |
  |
  x
  | 
 / \
o   o

and we can now visually move to any of the nodes, and our buffer is instantly brought back. Cool! The two branches correspond to the states 'world' and 'foo'. I have been undo-tree-mode for the last few weeks, and it works very well: usually I don't even notice it, but when I need the extra power, it's there.

I am told that UndoTree is inspired by the way the vim-text editor does this. Anyway, there is another very powerful feature in the vim undo-system that would be nice to have in emacs to: time-based undo. In vim you can e.g. say something like:

:earlier 5m

to go to the state of your buffer 5 minutes ago. That would be a nice addition for undo-tree-mode!

Update Tavis Rudd notes that pressing t in undo-tree-visualizer-mode (i.e.. what you see when your press C-x u) will give you timestamps instead of o and x:

                  |
                  | 
             18:54:20
                  |
                  |
             18:54:20
          ________|___ 
         /            \
     18:54:15       18:53:37
        |              |
        |              |
     18:54:15       18:53:37
     ___|___           |
    /       \          |
18:54:10  18:53:43  18:53:36