Hacker News new | ask | show | jobs
by afc 928 days ago
In my text editor (https://github.com/alefore/edge) I keep the undo/redo history always linear, which I find works pretty well.

So suppose the user does the following operations:

• Insert "Hello"

• Insert " world!"

• Undo once.

• Insert ", Cameron!"

At this point, undo operations would gradually transform the buffer thus: "Hello, Cameron!" => "Hello" => "Hello world!" => "Hello" => "". Obviously, one can redo at any point. The undo/redo days structure don't preserve the state, just the transformations (which are reversible).

The gist of it is that when you apply a modification to the buffer and the redo stack isn't empty, the redo stack gets flipped and inserted into the undo stack. If you undo a long list of transformations and then make a change, that long list is duplicated, but this hasn't been a problem in practice.

In case someone finds this interesting, this is mostly implemented here: https://github.com/alefore/edge/blob/28c031230a8babe888ffe1a...

2 comments

This is how traditional Emacs undo is implemented as well. I like it but it seems to be not the norm; it does take a little bit to get used to. (There's plenty of packages to transform Emacs undo into something more like a tree structure, though I don't personally use them because I'm used to the above behavior.)
Interesting, none of the editors I just tested (notepad / visual studio / sublime / github) works like this.

I think of undo/redo as "time traveling", going back to where I was one / two / several steps bevor. The mental model of your implementation is more akin of actually "doing" the undo. Like if you undo insert " world!", you create an action that deletes " world!". The timeline still goes forward, but now has a delete action.