6 ms·
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 ha
by thomastjeffery 3y ago
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 https://news.ycombinator.com/item?id=15381886
- trws 3y agoConsider my interest piqued. We’ve seen a couple of others in the space, notably Kakoune and Helix. What do you have in mind?
- thomastjeffery 3y agoTL;DR: Most (if not all) of the same features, just not as tightly integrated. Every feature is a piece of the puzzle that is your user config. --- Picture Emacs without a default keymap. That's a start. The user builds their own UX from scratch; bringing each feature into their config explicitly. Alternatively, the user just grabs a curated config like Doom Emacs. The difference here is that they can read it: all of it. Instead of writing a bunch of imperative elisp (that becomes its own web of circular dependencies), let's structure the config with some kind of purely functional additive data structure. That Piece Table I wrote is a good start. Instead of just piecing together letters, let's piece together UI and functions. This idea can apply to everything. I envision it as the next generation of shells, of web browsers, of operating systems: everything. Imagine Blender, but you the user add one fruit at a time. Where's the button to extrude mesh? Exactly where you put it; or nowhere at all! Software is made of incompatibility, and I'm sick of it. Where we should have borders, we have walls. Just imagine what it could be like if we tore them all down.
- Aerbil313 3y agoCompatibility arises from standardization, which only comes after maturity. I don’t expect software industry to mature until another hundred years or so.
- somat 3y agoI 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 3y agoYes, in Vim, repeated u's just continues undoing, while ctrl-r is for redos.
- derriz 3y agoWith 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 3y agoI 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 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 3y ago> 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.
- fiddlerwoaroof 3y agoThere’s a trick to remap space to automatically insert an undo point in vim: https://stackoverflow.com/a/4360415/13099 https://stackoverflow.com/a/4360415/13099 But, after getting used to vim’s commands, I find I go back to normal mode relatively quickly and so my undo steps are generally logical.
- scelerat 3y agoSimply stated, 'u' in vim undoes every change since the last insert. I suppose for some, "more granular" undo points could be useful, but I'm in such a habit of doing something discrete and then escaping insert mode, that I've never felt pinched by the potential for vim's large undos.
- thomastjeffery 3y agoThe "solution" is to simply leave insert mode more often. That works great if you are using Vim for editing. If you are using Vim for writing... well, not so much. Then again, if I am writing in Vim, I generally prefer the flow of actively editing what I wrote rather than undoing it. This really applies to Vim as a whole: if you enjoy its UX, it's damn near perfection. If you hate it, you can leave. If you love it, but want it to behave just a little differently...then you can probably accomplish that with a plugin/configuration. ...but if you want to change Vim's UX more than a little, you're fucked. It feels totally possible until you realize it just isn't.
- ColonelPhantom 3y agoWell, in Vim, "switching to normal mode" can be thought of as "ending an insert command" instead of "switching modes", which makes sense as soon as you realize that normal mode is, well, normal. So when you press "o", I don't think "switch to insert mode". I think "insert a line with the following text:", which can then be undone with u, repeated with ., or whatever else you want. At least that's my mental model of Vim, I don't know which is closer to reality.
- MrLeap 3y agoI'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/ https://store.steampowered.com/app/1537490/Tentacle_Typer/
- alpaca128 3y agoI am currently working on an editor. Definitely interesting to try different ideas just to find out why certain things in Vim are that way. Also the "." key is more complicated than I expected, the exact start of an edit operation depends on the behaviour of certain default keybindings. It just works so smoothly I had never thought much about it before. > Maybe one of these days I will get far enough past the ADHD wall to make it happen... That's definitely the most difficult part, for me it got easier at some point once it actually seemed realistic that I'd manage to finish it one day.
- thomastjeffery 3y agoThe coolest feature of Vim is its macros. They bring the entire UX into one cohesive feature. The keymap has meaning, because every key symbol is a character, and a macro is just a string. You can paste them, edit them, copy them, then play them back; all without ever leaving Vim's primary UX. Macros are stories written, not in vimscript, but in the language of Vim itself. Macros are also the reason I don't use Vim anymore. The keymap has meaning, and it shouldn't. Want to change your keymap? Good luck. I spent years in Vim. I conceptualized all of it. I built my muscle memory around it. Then I learned a new keyboard layout. I tried remapping the keys. Not only was that impossible (circular dependencies), it broke the conceptual map, too. I have offended the beast, and am welcome no more. What I really want is to start fresh. No defaults: just user config. Give me the pieces, and the glue to hold them together: I'll do the rest.
- linsomniac 3y ago>Macros are stories written, not in vimscript, but in the language of Vim itself. Last year I hit upon the idea that vim's commands are like a bytecode that my brain outputs and vim interprets. I guess that's true of any editor UI, but it just feels more appropriate in the vi case.
- teo_zero 3y ago> I tried remapping the keys. Not only was that impossible (circular dependencies) I don't get this. To swap x and y is easy: noremap x y noremap y x Of course you can't do it with map, that's why noremap exists.
- truculent 3y agoAs what point does a fully featured undo/redo system start to look like git (/VCS of choice)? Once you add deliberate checkpoints and the tree structure from the article, it feels like you’re more than halfway there.
- afc 3y agoThis resonates with me. I use undo/redo up to a point, but eventually I just reload the file (which I'm saving frequently) or just check it out (from git, mercurial) again.
- truculent 3y agoRight - using undo/redo for quick or ephemeral changes, before solidifying into something (more) permanent feels very similar to me to making a bunch of small commits while working on/exploring something before cleaning them up into semantic chunks with a rebase. Maybe there’s some implicit idea here like treating a commit as an aggregate of a bunch of atomic actions (i.e what undo/redo act on)
- sureglymop 3y agoAs a music producer who has been working with various DAWs, I've always been super jealous that programmers have git. Not just for version control but also for collaborations. I always thought, it must be possible because sound is just a list of samples (numbers). Kind of like how a binary executable or assembly code is just a list of values or instructions. Unfortunately most music software and plugins are proprietary as this industry did not have the same political movements (GNU, F(L)OSS, OSS, etc) that the computer industry had and most professional software has been created for professionals by companies. It's interesting though because software like Ableton Live has an unlimited undo history but since it is proprietary one can't really look at it.
- LoganDark 3y ago> Maybe one of these days I will get far enough past the ADHD wall to make it happen... I have that hope for literally hundreds of things... but I know I will never actually get to do any of those things. I can think of any one of them right now and be unable to even try. I hate this existence.
- afc 3y ago> 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. This is more or less the philosophy of the editor I've been working on (and using ~exclusively) since 2014: https://github.com/alefore/edge/tree/master https://github.com/alefore/edge/tree/master Some parts of the UI are still defined in the compiled language (so don't fully fit your philosophy yet), but a big part of the UI comes from the configuration loaded at runtime: every time the editor starts, it interpretes and runs this configuration defining the UI: https://github.com/alefore/edge/blob/master/rc/hooks/start.cc https://github.com/alefore/edge/blob/master/rc/hooks/start.c... (This file is not compiled into the editor, but loaded and executed directly at runtime; the format of that file is my editor's extension language/configuration (the equivalent to emacs lisp or vimscript), which just happens to be a garbage collected C-like language.)