News for hackers. Stuff that matters.
Re:A bug I wish I hadn't caught by munificent on Thursday August 15, 2019 @12:19PM (#20706587)
The parlor trick isn't a useful feature in practice. If a user drags a Note around a bunch, drops it, and then selects undo, what they really want is to undo all the way back to its location at the beginning of the drag. They don't want to rewind the entire drag procedure one pixel at a time.

I've dealt with this issue in various tools and level editors a few times. It can be annoying. The fundamental problem is that if your tool has undo (which it should), the cleanest way to architect it is such that every state change goes through undoable operations.

But that means that even in the "middle" of an operation like dragging something, or painting a long meandering line, you need to be creating and processing individual undoable steps so that the user can see the operation as it proceeds.

But once the operation completes, if they undo, they (usually) want to undo the whole batch of them, not each tiny step. A closer-to-home example of this for most programmers is their text editor. Type a sentence quickly and then hit undo. You don't want that to just undo literally the last character.

There are two ways I know to handle this:

1. If memory is less of a concern, I keep the series of individual undoable steps and then wrap them up in a single "multi-step" undoable operation. Then, in the main undo queue, replace them with that wrapper so that they are all processed as a single operation. When you undo the wrapper, it just undoes all of its child steps in reverse order.

2. If memory is more of a concern, I add support for collapsing a series of undoable operations into a new larger one that can represent the entire aggregate change more efficiently. This is more work because you need to write separate code for each kind of operation that can be batched this way.

Re:A bug I wish I hadn't caught by reificator on Thursday August 15, 2019 @12:55PM (#20707048)
> Type a sentence quickly and then hit undo. You don't want that to just undo literally the last character.

I am continually irritated by this behavior.

Yes, I do want to undo one operation. If I need to go fast and have little regard for correctness I can hold the button down.

Don't make me play the game where I hit undo, it undoes the whole sentence (or several), so I hit redo to bring it all back, and then I have to click backspace 5 times to get to where I wanted. Worse when I'm using multiple cursors and doing operations of different lengths to each line.

Re:A bug I wish I hadn't caught by parliament32 on Thursday August 15, 2019 @03:17PM (#20708670)
Sounds like you need Vim in your life.

To keep things short: Whenever you want to insert some text you need to switch to Insert mode. When you're done you Esc out back to Normal mode. Undo will undo everything you did inside the last Insert.

Re:A bug I wish I hadn't caught by reificator on Thursday August 15, 2019 @05:23PM (#20709802)
> Sounds like you need Vim in your life.

> To keep things short: Whenever you want to insert some text you need to switch to Insert mode. When you're done you Esc out back to Normal mode. Undo will undo everything you did inside the last Insert.

That's a more extreme version of the behavior I'm objecting to. Why would I prefer that?

Re:A bug I wish I hadn't caught by parliament32 on Thursday August 15, 2019 @05:58PM (#20710117)
I'm having trouble understanding what you want.

Undo is for undoing an action, like inserting a bunch of text.

If you want to delete one character at a time backwards... use the backspace key?

Re:A bug I wish I hadn't caught by reificator on Thursday August 15, 2019 @06:44PM (#20710433)
Honestly the issue is mostly due to wanting a slightly smaller, but not one character, undo. I think the problem is just that the things that I view as pauses and separate actions are almost always shorter than what the undo function sees, and undo undoes enough that it's quicker to redo and backspace than retype.
Re:A bug I wish I hadn't caught by toast0 on Thursday August 15, 2019 @10:30PM (#20711644)
> That's a more extreme version of the behavior I'm objecting to. Why would I prefer that?

Put something in the wrong place (probably via pasting, but it's not always clear to a screen editor if you pasted or just typed quickly)

Re:A bug I wish I hadn't caught by reificator on Friday August 16, 2019 @12:20AM (#20712146)
Typically when I paste something, I type something beforehand, and then paste it in, undo it, and it undoes what I typed before.

This is worse when I'm using multiple cursors, which is usually me manually cleaning up some data.

Re:A bug I wish I hadn't caught by bin0 on Thursday August 15, 2019 @06:30PM (#20710346)
Still use vim. You can use something like "5db" to delete the previous 5 words. For more precision, "5X" will delete your last five characters. And if you have a very specific use case, macros are a big help. If you have a very specific and recurring use case, you can script in vim script, ruby, perl, python (2 & 3), tcl, racket, and lua. There may well be support for others of which I am not aware.
Re:A bug I wish I hadn't caught by weaksauce on Thursday August 15, 2019 @02:49PM (#20708363)
Undo is an transactional operation... backspace five times is precisely what backspace is for and would make undo less powerful if it undid every single keystroke.
Re:A bug I wish I hadn't caught by reificator on Thursday August 15, 2019 @06:46PM (#20710445)
My problem is that my mental model for what is an undoable transaction is almost always smaller than the editor's, to the point where I try to undo, get surprised by how much was lost, and then redo and control+backspace until I've deleted what I need.
Re:A bug I wish I hadn't caught by mark-r on Thursday August 15, 2019 @05:21PM (#20709784)
The sane way to do that is to split the UI and edit, so that changes in the UI (like pixels while dragging) don't enter the history. I worked on one application that did this, and the results were almost ideal.
Re:A bug I wish I hadn't caught by GuiA on Thursday August 15, 2019 @01:06PM (#20707187)
1a. As a bonus, offer coarse undo and granular undo (where granular undo always undoes an atomic operation, and coarse undo undoes the “multi-step” operation if applicable, to the user.

You can imagine a lot of quality of life improvements built on top of that depending on your application: eg if the user holds granular undo and there are many combinable operations (eg the user drew a single stroke that is represented by hundreds of single pixel additions), you may snap to a single coarse undo. Or you can offer a visualization of the underlying operations and what they map to, etc.

(see sibling comment by ‘reificator)

Re:A bug I wish I hadn't caught by munificent on Thursday August 15, 2019 @06:19PM (#20710265)
That's a viable solution too, though it comes at the price of UX complexity. HN folks tend to undervalue simplicity because they love learning new features and want all the things. But often, the best user experience for the most people means sacrificing some operations that are technically useful but not enough to carry their weight.
Re:A bug I wish I hadn't caught by GuiA on Thursday August 15, 2019 @07:20PM (#20710657)
Yup, ultimately the balance between simplicity and technical operations available will depend on one’s own specific use case.

That said, for technical applications, I think it makes sense to expose as much of your features as possible in terms of composable, atomic units and operations.

If Cmd-Z maps to a black box “undo” command, then anything on top of that will seem like it comes at an interface complexity cost.

If, however, Cmd-Z is a configurable shortcut like any other that, by default, happens to send a “undo 1 user operation” message to a “history” module, that’s a different story. Now your users can modify it to be “undo one high level operation” instead, or “undo all consecutive operations that are the same in kind”. Or perhaps they want Cmd-Z to undo the last discrete operation, and Cmd-Alt-Z to undo the last logical operation. Or maybe there’s a strong temporal dimension to their work and they want the undo logic to take that into account.

Likely not the kind of thing you’d want for a mobile photo sharing app meant for a wide audience; but maybe the kind of thing you’d want for a complex, specialized data processing tool on the desktop.