I am working on a multi-file editor that uses CodeMirror v6 as the underlying code representation of a GUI editing system. I am interested in making file deletions, renamings, and creations undoable.
I have implemented this using StateEffects with invertedEffects (the draft PR is here for anyone interested, but its particulars aren’t relevant to my question). On file navigation, we clear the history (in future we’ll just create new EditorViews which is preferred), but I would really like to have these history items persist beyond navigations.
Is there a way to filter down the historyField values to only those including certain Annotations, then load them into the new history / EditorView on navigation? I started to go down that that route but the docs say the following:
Should probably only be used when you want to serialize or deserialize state objects in a way that preserves history.
And that’s not all I’d be doing. Should I just not be using the CodeMirror history API to store these effects: is it bad practice?
The editor history is designed as a document-local thing (it lives in EditorState, after all), not an app-wide cross-document thing. You might be better off implementing a completely separate history, if what you want is an app-wide undo stack (but then again, that may also not be what you want, since if you have document A focused and the last change was in document B, you probably don’t want ctrl-z to make a change to that other document).
Okay thank you, I figured as much. I will experiment with keeping undoable app events outside in a separate history that either conforms to CodeMirror’s interfaces or just is a pared-down EditorView. Then I can try using that as the starting history when clearing/recreating our code editor’s EditorView.
I created a pared-down HistoryView class that wraps an EditorView. At runtime, a local history target EditorView can be registered. If a local history target is registered, dispatches to the HistoryView are forwarded to the target as “pointer events” with inverted effects that allow undoing the forwarded event to trigger an undo from the HistoryView, an idea I borrowed from @FilipSzutkowski’s helpful write-up here.
I store this HistoryView in the same place as our (now “local”) EditorView instance, and made all my undo buttons and whatnot use its undo and redo functionality to provide fallbacks if global history depth is available but local isn’t. The upshot is that users get file system edits interleaved with their normal local code edits until they navigate to another file, then the global history persists and the interleaved edits disappear, but direct access to the file system edit history lives on and is still available if you undo any local edits, like “before” your local edits.