cessen / ropey

A utf8 text rope for manipulating and editing large texts.
MIT License
1.04k stars 46 forks source link

Persistent Buffer History #98

Closed Riolku closed 2 weeks ago

Riolku commented 2 weeks ago

Hello!

Sorry if an issue isn't the best place for this. I'm looking into implementing persistent history akin to neovim - when you close neovim and then reopen it, you can undo changes made outside your current session. undofile is the option for this

To implement this with ropey, I figure it'd be best to collect the history of ropes and write them to disk. However, I'm not sure how to ensure they share data when they are reloaded. I am not aware of helix having this feature.

Any ideas?

cessen commented 2 weeks ago

To implement this with ropey, I figure it'd be best to collect the history of ropes and write them to disk.

Storing a list of ropes as your edit history probably isn't a great approach, even in memory. Although cloned ropes do share data to some extent, that sharing is done in 1kb blocks. So every 1 character edit in your history will take a minimum of 1kb of space, which is wasteful to put it mildly.

Additionally, a history of rope clones won't store any information about the edits that made them, so figuring out what changed between ropes (to e.g. jump the view or cursors there) will become quite expensive.

What you probably want to do instead is something like storing a history of the actual edits made (e.g. "insert A here", "delete B here") so that you can play them back in reverse for undo. Take a look at Helix's implementation of what it calls "change sets" and "transactions" for some inspiration.

Then writing that to disk is simply a matter of serializing the undo data. (You might also want to store a hash of the text contents with the on-disk undo data, so the next time you launch your editor you can make sure the text hasn't changed, since the undo stack will be invalid if it did.)