Text undo that doesn't lose your edit history
There's a problem with undo behavior in text editors: when you type, undo, and type some more, the stuff that you originally typed becomes lost forever.
I got an idea for a simple solution to this: instead of blowing away the undo stack, add the undo+edit as one new combined action on top of the stack. For example, if you type A, then B, then undo B, then type C, normally the undo stack would become [A,AC]; but in my solution it would be [A,AB,AC]. This means as you keep typing, undoing and redoing, the stack only ever grows, never shrinks. You can always unwind all the way back to the beginning, through all the discarded drafts.
Of course this behavior won't be perfect for everyone. But it's an interesting option to explore, because it's very simple (no branching UI), preserves all history, and still keeps the number of undo steps manageable. So it could be a kind of sweet spot.
Since I couldn't find any online demos of this, I made a small demo myself. Here's a textbox - type some stuff, Ctrl+Z, type some more, then try undoing and redoing:
Made with
TinyMCE, with a surprisingly small code change:
--- a/modules/tinymce/src/core/main/ts/undo/Operations.ts
+++ b/modules/tinymce/src/core/main/ts/undo/Operations.ts
@@ -65,11 +65,6 @@ export const addUndoLevel = (
// Get a non intrusive normalized bookmark
newLevel.bookmark = GetBookmark.getUndoBookmark(editor.selection);
- // Crop array if needed
- if (index.get() < undoManager.data.length - 1) {
- undoManager.data.length = index.get() + 1;
- }
-
undoManager.data.push(newLevel);
index.set(undoManager.data.length - 1);
@@ -131,7 +126,7 @@ export const undo = (editor: Editor, undoManager: UndoManager, locks: Locks, ind
if (index.get() > 0) {
index.set(index.get() - 1);
level = undoManager.data[index.get()];
- Levels.applyToEditor(editor, level, true);
+ Levels.applyToEditor(editor, level, false);
editor.setDirty(true);
editor.dispatch('Undo', { level });
}
Back to Vladimir Slepnev's homepage