Hacker News new | ask | show | jobs
by stephen272 1944 days ago
For anyone that uses emacs, there is an excellent plugin "undo-tree" that solves this problem in a slightly different way. Everytime you undo a series of actions and then perform a new action, it creates a branch in the "tree". You can then visualize the tree and move through it quickly your entire buffer history.
12 comments

Another cool thing about undo in Emacs is that it's context aware.

By default, you can select any block of text and the undo command will cycle through the changes only from that region of your buffer.

whoa this is cool

does it understand syntax boundaries like curly braces / functions? ('undo within function' would be key). or just line #?

That concern is isolated to your region selection tool, and orthogonal to the undo functionality :-) So, you could select by lines, or intelligently select by parentheses/braces, etc. And ask these are nicely composable, so you could easily set up custom shortcuts if you don’t like the sequence of keystrokes.

For eg, see https://www.johndcook.com/blog/2017/08/09/selecting-things-i...

Regions in emacs do not need to consist of whole lines.
For those that use vim, gundo.vim visualizes the "undo-tree" and allows you to preview / jump to any revision: https://github.com/sjl/gundo.vim
There's a fork called mundo which has an inline diff mode that I'm a big fan of — https://github.com/simnalamburt/vim-mundo
Came here to post this. The undo tree is actually built into Vim, but I didn't know about it until I discovered Gundo a decade or so ago. I rarely use it, but it's still installed and has saved me hours of work on a few occasions.
Even without undo-tree, Emacs undo history is "persistent". By that I mean that changes aren't overwritten, so the statement in the article that undoing stuff and then making edits loses the undone changes is not true for Emacs. You just have to undo back through the new edits, then you will start to redo the old undone edits, and so on. It can be tedious, but just the knowledge that it's all there is quite liberating.

Another vanilla feature I sometimes use to keep track of old code is the "kill ring". Just cut the old code and it will be available in there later if needed.

And to get something closer to OP there is always undo-propose.el[1].

[1] https://github.com/jackkamm/undo-propose-el#screenshot

This this this. It was the first thing I missed in Vim when I switched. You also don't lose in Vim, as it keeps it the history as a tree, but it is harder to navigate the tree than Emacs' linear history.
This was my first thought. A timeline is nice, but the problem with a linear undo history is that if you undo and then edit, you lose access to the state before you undid. A tree is clearly the right structure for undo history.
You could just append a new state to the end of the timeline when you “undo”, so you never lose history. This is how undo works in Emacs by default.
Heck it's how boring business apps handle bookkeeping data since forever. You never delete a record to correct a mistake, you create a new record to do it.
The tree structure is inherently flawed for storing undos when using features like undoing within a specific region, because the new state doesn't map to any previous node on the tree.

By default, Emacs has a linear undo structure, while still allowing you to never lose history.

Newb emacs user here. Heavily reliant on spacemacs and tutorials and copy-paste, but I use it often.

The undo-tree terrifies me.

It’s easier to mentally map that the default behaviour undo/redo for Emacs (which is not unreasonable, just complex).

The source for undo-tree contains documentation which very effectively describes the way the library works with examples and comparisons with how Emacs does things by default: https://gitlab.com/tsc25/undo-tree/-/blob/master/undo-tree.e...

I was too at first, until I learned the shortcut keys (to move to the next branch specifically), then everything was fine.
On this point, C-h m yields a complete list of keybindings for all modes active in whatever buffer you do it in.

More generally, for anyone new to Emacs and struggling as I once did, I can't recommend strongly enough that you learn how to use the help system (C-h C-h) and the built-in manual (M-x info). Emacs can teach you a great deal about itself, and these are the ways it does so.

It's easier than it looks! Poke around with the arrow keys a little. You'll get the hang of it pretty quick.
Tangentially, have you had the issue where undo-tree just uses a ton of memory and makes everything unusable?
And if you use IntelliJ/Android Studio there's Local History, which shows your git revisions but also periodic versions of your code outside of your commits
Undo in region is also pretty useful if you want to revert part of your code but not all.
It can even persist history across restarts if you set undo-tree-auto-save-history.
Came here to post this. Tho most times my undo tree are single characters.
You should work on you long-term memory for the language's keywords, or on your variable naming ;-)

EDIT: Or are you programming in APL?

guilty on the latter. tho only contributors to my packages and coworkers complain about it. I am fine with it.
I immediately thought of this, it is so good, like a source control-lite.
Something I always thought might be useful: I want to select a region of the code, and undo that, while keeping everything else unchanged.