bazed-editor / bazed

The baz editor
Apache License 2.0
26 stars 3 forks source link

Make undo remember cursor position and selection #47

Closed elkowar closed 1 year ago

elkowar commented 1 year ago

This is a problem xi-editor had too (https://github.com/xi-editor/xi-editor/issues/458): Undo is done as part of the CRDT engine, which does not know about cursors. I see two viable implementation strategies:

Additionally, any other marks also need to be aware of undo: Some, if not most, should just be recomputed (i.e. marks for inlay hints, or whatever we may use them for). Others (i.e. the carets of users other than the one that just did the undo) should apply a coordinate transform.

Another very viable idea

Instead of remembering where exactly the cursor was, just use a coordinate transformation to move the carets accordingly, and then (optionally, no reason not to make this configurable) ensure that the caret is moved within the range of text that was affected by the undo / redo action by moving it into that range if required. That way, we can ensure users are always aware of what changed. We'd simply need to ensure that in the simple case (inserting, then undoing) the cursor is where the user would expect it to be, i.e. at the start of the range that had been undone.

We could also just move the viewports to visualize the area that the undo happened in, without actually moving the cursor. That may actually be a preferred UX for many users.

elkowar commented 1 year ago

From discord:

so every mark has a u32 offset, a kind, an affinity, and maybe a user id (worst-case scenario). that makes it about 12 byte.

let's say we have a pessimistic number of about 100 marks, that makes it 1.2kb

let's now say we just naively store all marks for each history revision, at about 2000 undo history steps that makes for a worst-case size of 2.4mb just to store caret history

let's, more realistically, assume we just recompute most marks anyways, so we just care about the ~1-5 user carets for the revision history that would mean 120kb for caret history I don't think that's an issue, is it? ~ ElKowar

further:

Actually, how do we deal with non-linear undos? (not relevant in most cases, but may be relevant in a multi-user situation, as well as when plugins are involved -- also simply the fact that it's expressible in our datastructure means that we'd need to somehow support it

by this I mean the following: rev 1: cursor is at 5, doc has 5 characters rev 2: cursor has moved to 10, we inserted 20 characters rev 3: cursor has moved to 15, we changed char 2

undo rev 2: cursor jumps to 5, document has 5 characters undo rev 3: ¿where is cursor? How does it know that the revisions cursor position cannot be reapplied? Do we keep track of the earliest thing we undid, and don't apply caret positions from any edits after that? ~ ElKowar