Fun With Undo-Tree-Mode
No more. This ends now. This will not stand!
What’s my problem, you ask? I’ll tell you what. Emacs’ stupid undo system is my problem. Humor me for a second; fire up Emacs, and type the following:
foo bar baz
Still with me? Good, now press
…baz disappeared. “Well, duh! If you’re gonna whine about the fact that C-u doesn’t undo, then maybe you shouldn’t be using Emacs…” you say. Were that my issue, I’d be inclined to agree. Unfortunately, the problem is much worse. Enter the following into your buffer:
C-x u C-x u
See that? Yeah… Not OK. The buffer should be:
with the entry of
bar having been undone. Instead, the buffer is:
foo bar baz
with the entry of
oof and the undoing of the undoing of the entry of
baz having been undone.
Apparently, an undo operation itself goes onto the undo stack in Emacs. Meaning that if you undo enough times, it will redo all the undone operations, then undo them again, then undo the operations before. This lets us get the buffer back into any state it has ever been in, which sounds nice on paper. In practice, it’s yet another way that Emacs goes its own way, the rest of the world be darned. And I gotta say, its pretty annoying. In a normal program, you can just hold
Ctrl+u, and watch the undoes fly. In Emacs, you get to press
C-x, release, press
u, and release to undo one thing. Then do it again
Luckily for us, this being Emacs, there is likely a better way out there.
Undo tree mode is a minor mode for Emacs that helps us deal with this undo behavior. In the short amount of time that I’ve played with it, I’d say it makes the on-paper benefit of Emacs’ undo behavior a reality. But first, some installation.
Undo-tree-mode is in Melpa stable, however, I was unable to get it to work. To install undo-tree-mode, you can install it via Melpa, then add the following to your
Unfortunately, when I restarted Emacs, I got the following error:
Symbol's function definition is void: global-undo-tree-mode
does nothing to alleviate this situation, neither does opening
undo-tree.el and entering:
However, I was able to install it manually. First, I deleted all the files for undo-tree-mode from my
.emacs.d/ directory. Then I downloaded the current version of the plugin from the author's website, and placed it in my
~/.emacs.d/, naming it
undo-tree.el. Finally, I added the following lines to my
(add-to-list 'load-path "~/.emacs.d/") (require 'undo-tree) (global-undo-tree-mode t)
That first line is only required if you haven’t already added it elsewhere. Restart Emacs, and you should see that the
Undo-Tree minor mode is active.
Climbing The Tree
Now, let’s try that previous sequence of events.
foo bar baz C-x u
A new window should appear with the following in it:
s | | o | | o | | o | | o | | x
Neat. This represents the operations that you did. Try clicking through them (you can also use the arrow keys to browse). Each node is a state of the document,
x is the current state, and
s is the initial state. Select the node two nodes up from the leaf to undo entry of
baz. Lets continue our sequence:
oof C-x u
You should see a new tree that looks something like this:
s | | o | | o | | o | | o | / \ x o | | o
If you click around the tree, you’ll see the various states of your buffer. You’ll see that it is simple to restore any previous state of the buffer.
Now this is something I can get used to!