[HN Gopher] Text Editor Data Structures: Rethinking Undo
       ___________________________________________________________________
        
       Text Editor Data Structures: Rethinking Undo
        
       Author : starfreakclone
       Score  : 106 points
       Date   : 2023-12-11 15:27 UTC (7 hours ago)
        
 (HTM) web link (cdacamar.github.io)
 (TXT) w3m dump (cdacamar.github.io)
        
       | linsomniac wrote:
       | I just skimmed it, but it looks like vim really has undo/redo
       | "solved":                   - Modal editing makes for nice "undo"
       | points, clarifying whether undo should undo "World!" or "!".
       | - "g-" and "g+" eliminate the "orphaned redo".  They walk the
       | entire undo/redo tree rather than just the linear undo/redo.
       | - Time travel undo/redo is really handy when you want to go to
       | where you were on the wall-clock.  ":earlier 15 minutes" takes
       | you to the code as it was 15 minutes ago.
        
         | thomastjeffery wrote:
         | Don't forget about the Gundo plugin: it lets you navigate your
         | tree of undo history.
        
           | JetSetIlly wrote:
           | Gundo is great. There is also mundo, which is a fork of
           | gundo. And, undotree, which doesn't require python support.
        
         | bee_rider wrote:
         | I love vim but I actually find undo/redo to be one of the few
         | annoyances of the program, because of the whole linear
         | undo/redo thing. So I guess I need to look into this g+
         | option...
        
           | thomastjeffery wrote:
           | As I mentioned elsewhere, gundo is really helpful for
           | navigating the undo tree.
           | 
           | My favorite thing about vim's flow is that it isn't just
           | limited to undo/redo: you can re-perform your most recent
           | action anywhere using the . key.
        
         | 38529977thrw wrote:
         | > ":earlier 15 minutes" takes you to the code as it was 15
         | minutes ago.
         | 
         | TIL. Very cool. tnx
        
         | g0xA52A2A wrote:
         | Just to emphasize part of your comment as I think a lot a
         | people aren't fully aware - Vim has an undo _tree_
         | https://vimhelp.org/usr_32.txt.html#usr_32.txt
        
         | eviks wrote:
         | Far from solved
         | 
         | Modal editing isn't enough if you type whole
         | sentences/paragraphs of text within a single insert session
         | 
         | Also undo in selection is required to "solve" it, as well as
         | semantic points besides "last 15 minutes" (like "last saved
         | session" or "last time you quit the editor")
         | 
         | Also UI with a diff is sometimes better than having to
         | undo/redo to see changes
        
       | globular-toast wrote:
       | Emacs undo-tree does everything I need. Emacs also supports undo
       | in region which most editors don't seem to support and wasn't
       | covered by the article.
       | 
       | I actually used regular Emacs undo for years which lets you get
       | everywhere in the tree with a kind of tree traversal but you
       | won't know where you are. I resisted undo-tree for ages but it's
       | definitely worth it as it stays out of the way until the occasion
       | you might need to use it.
        
         | kleiba wrote:
         | Emacs's undo is great in that invoking an undo command is
         | itself undoable. And that is different from just your standard
         | redo. It definitely needs some getting used to but it is very
         | powerful.
         | 
         | But I think your second points deserves an even bigger mention:
         | Emacs has the ability to apply undo only to a certain "region"
         | - which in Emacs parlance is basically just a selection of
         | text. For those of you who have never seen it: imagine two
         | parts of a file you're editing, say one part at the top, one at
         | the bottom. You start by editing the first part (top) and then
         | then move your cursor somewhere down to the second part of the
         | file (bottom) to do some more editing there. But then you
         | realize that your edits in the first part of the file were
         | baloney. In most other editors, if you wanted to undo them,
         | you'd be forced to also undo the edits in the second part of
         | the file. In Emacs, however, you can simply select the first
         | part at the top of your file - if you hit undo then, it will
         | only undo the last edits done _inside that selection_ and leave
         | all edits outside of that region untouched.
        
           | bornfreddy wrote:
           | Wow, that's genius! Thank you for explaining, TIL.
        
           | layer8 wrote:
           | What happens when, for example, you atomically replace
           | "mouse" by "elephant", then select "epha", and then region-
           | undo?
           | 
           | The reason most editors don't implement this is probably that
           | it's hard to conceive of how it should behave in the general
           | case. (That's not to say that the way Emacs is implementing
           | it isn't good and useful.)
        
         | submeta wrote:
         | Wow, been using Emacs for decades and didn't know about ,,undo
         | in region". Thanks for sharing!
        
           | ska wrote:
           | It's one of those things like rectangle commands; once you
           | know they exist it's hard not to miss them in editors that
           | don't support.
        
         | eviks wrote:
         | Indeed, undo in regions is the second best feature of emacs
         | undo, wish it were more popular
        
       | thomastjeffery wrote:
       | Thinking about undo/redo is a great place to start thinking about
       | your text editor's underlying data structure.
       | 
       | I went down this rabbit hole a while back. I had to really
       | dig[1]: it's been 5 years...
       | 
       | ---
       | 
       | Data structures aren't the only interesting rabbit-hole, though.
       | 
       | UI/UX doesn't get nearly as much attention as it deserves. There
       | are really only two that I am aware of: Notepad and Vim. Vim's
       | modal editing results in the user explicitly defining undo/redo
       | points. You can even use the "." key to re-redo! Everything else
       | essentially boils down to a greater or lesser version of Notepad:
       | The user can't predict what state undo will take them to.
       | 
       | Something I have wanted to create for a _long_ time (definitely
       | more than 5 years) is a new modal editor. I don 't want yet
       | another vi clone: I want something that is defined from the
       | ground up by user configuration. Maybe one of these days I will
       | get far enough past the ADHD wall to make it happen...
       | 
       | [1] https://news.ycombinator.com/item?id=15381886
        
         | trws wrote:
         | Consider my interest piqued. We've seen a couple of others in
         | the space, notably Kakoune and Helix. What do you have in mind?
        
         | somat wrote:
         | I still use a lot of nvi on openbsd. and it has a strange quirk
         | to it's undo.
         | 
         | so "u" undoes your last action. but if you hit it again it
         | undoes the undo, a redo if you will. I did not really think
         | about it much, just accepted that was how nvi worked, a single
         | level undo. But that is not true at all. the trick is you have
         | to "u" undo then "." repeat previous action and you get the
         | full undo stack. and, like the parent post mentioned, you also
         | get a full redo stack the same way. Get it to redo then repeat
         | previous action.
         | 
         | I am not exactly sure what vim does, But I suspect this is one
         | of it's improvements.
        
           | jyscao wrote:
           | Yes, in Vim, repeated u's just continues undoing, while
           | ctrl-r is for redos.
        
           | derriz wrote:
           | With vim, "u" always moves back in time through the undo
           | history, CTRL-r forward. "." repeats the last action which
           | changed some text but not stuff like moves or going
           | forward/backward through the undo history.
           | 
           | nvi sounds very weird to me.
        
           | wolverine876 wrote:
           | I can't believe that, in 16 minutes, nobody else on HN had
           | the answer: nvi is following original, authentic vi behavior,
           | not this newfangled stuff. The Vim manual explains it:
           | How undo and redo commands work depends on the 'u' flag in
           | 'cpoptions'.       There is the Vim way ('u' excluded) and
           | the Vi-compatible way ('u' included).       In the Vim way,
           | "uu" undoes two changes.  In the Vi-compatible way, "uu" does
           | nothing (undoes an undo).            'u' excluded, the Vim
           | way:       You can go back in time with the undo command.
           | You can then go forward again       with the redo command.
           | If you make a new change after the undo command,       the
           | redo will not be possible anymore.            'u' included,
           | the Vi-compatible way:       The undo command undoes the
           | previous change, and also the previous undo       command.
           | The redo command repeats the previous undo command.  It does
           | NOT       repeat a change command, use "." for that.
           | 
           | https://vimhelp.org/undo.txt.html
           | 
           | (Actually, I have so rarely used vi that I'm relying on the
           | implications of the Vim manual that it's original vi
           | behavior.)
        
         | wolverine876 wrote:
         | > Vim's modal editing results in the user explicitly defining
         | undo/redo points.
         | 
         | ? How? Does switching to normal mode create an undo/redo point?
         | Someone asked me if the granularity of Vim's undo/redo could be
         | increased (i.e., more frequent undo/redo points). In what they
         | demonstrated, Vim's granularity seemed less than other
         | applications (i.e., undo/redo acted on relatively large chunks
         | of input); in some brief research, I didn't find a solution.
        
         | MrLeap wrote:
         | I'm working on a new modal editor. There's a demo on steam.
         | It's definitely not a vi clone.
         | https://store.steampowered.com/app/1537490/Tentacle_Typer/
        
       | johnea wrote:
       | Sorry, but the page you were trying to view does not exist <-- ?
        
       | hasoleju wrote:
       | Reading the comments on how vim and Emacs have implemented
       | Undo/Redo with various options was very helpful. I personally
       | don't use these editors, but I'm working on a graph drawing tool
       | where the user usually modifies multiple parts of the graph.
       | Right now we only have linear redo/undo implemented. Reading
       | about all this other options is really helpful. Especially the
       | Time travel and the regional undo are very smart features that
       | are also very helpful for all graphic based editors.
        
         | 3dGrabber wrote:
         | > Time travel and the regional undo
         | 
         | Jetbrains' IDEs have both of them and more. The feature is
         | called "Local History". [1] You can see the history of an file,
         | a selected region of text, or even your entire project. It can
         | undo file deletions/moves/renames. It feels like a personal
         | "automated git without the git hassles". It has got me out of
         | some really bad situations.
         | 
         | [1] https://www.jetbrains.com/help/idea/local-history.html
        
       | benj111 wrote:
       | I'm surprised there isn't much discussion of data structures
       | here, as that would inform an undo algorithm.
       | 
       | I infer from 'PieceTree'
       | 
       | That this is a binary tree based piece chain.
       | 
       | That makes undo really easy, especially character by character.
       | 
       | Nice explantation of piece chains
       | 
       | https://www.catch22.net/tuts/neatpad/piece-chains/
        
       | lrivers wrote:
       | If you are looking for counter examples, take a look at Excel on
       | windows. It undoes in multiple windows.
       | 
       | Say you have two documents open. You make a change in the first
       | then change the second document then go back to the first and
       | make a change. One document has two changes and the other has
       | one.
       | 
       | First undo impacts document one. Second alters document two.
       | Infuriating
        
         | EvanAnderson wrote:
         | Yes. This is arguably the most infuriating implementation of
         | undo/redo that I've used in any application.
         | 
         | It's worse than an undo that just wipes-out the document. In
         | that scenario I'd just not use the feature.
         | 
         | The behavior in Excel tricks you into using the feature by
         | working as you'd expect in a single document scenario. Then you
         | open a second document and end up trashing one or the other
         | when you undo the wrong thing.
         | 
         | I don't know how anybody ever thought this implementation was
         | the right answer. Ever.
        
       ___________________________________________________________________
       (page generated 2023-12-11 23:00 UTC)