ci_edit icon indicating copy to clipboard operation
ci_edit copied to clipboard

Redo Tree

Open aaxu opened this issue 7 years ago • 3 comments

A tree of redo chains where every path from the root to a leaf is a "redo chain." This is actually really cool since sometimes when I undo to see old code and then I accidentally type 'z' (cause my shift key is breaking :( ), I lose all my redos.

How do you think we should allow the user to access these different chains? I think it might be cumbersome to have the user tag the redo chain every time they start a new branch (undo and then make a new non-trivial change). Maybe we could make a new class for redo chains that allows for nice printing and show those in some compact form? I don't know how we would effectively show them all on one screen though.

aaxu avatar Nov 01 '17 18:11 aaxu

If the tree had a reasonable traversal pattern, it could appear linear to the user (or like a ring).

[Note this is just brainstorming. It's not a formal design. I'm just chatting]

Maybe similar to a preorder search, that 'walks back up' to the prior bifurcation before taking the next branch. The root would be the initial state of the file (maybe empty or with the contents that ci_edit first sees it in). Each node of the tree would be able to have an arbitrary number of children. The children could be appended (not sorted) so they maintain the chronology.

So there's a bit of an oddity where traversing some branches will 'undo' things when redo is called, because to get to the next branch the current branch needs to be undone. An exception would be the right-most branch, where we'd want to stop the iterator* on the right-most leaf.

To traverse, the iterator would need some prior memory/state for where it was, to avoid going up and down the same branch (getting stuck). I think we may just need a number of state values equal to the depth of the tree. That may give us enough of a trail to avoid revisiting the same child repeatedly. i.e. go to the child that is next (in left to right order) based on the index state in that node. Though it may be simpler to put an index state on every node (though many would be either at index 0 or index childCount - 1).

So the all-the-way undone would be at the root node. The all-the-way redone would be right-most leaf. And along the way, the root node may be visited N times (N being the number of immediate children). Hmm, I suppose any node would be visited N+M times (M being the number of parents, which for the root node is zero and all others would be one (if M were more than one, it'd be a graph rather than a tree)).

*of the tree

dschuyler avatar Nov 03 '17 03:11 dschuyler

I was thinking of that at first, but then some people use undo a lot while coding and it seems unnecessary to save every branch, so maybe we should only save if the number of continuous undos exceeds some number K. Then I was thinking what would happen if someone typed without ever hitting backspace, move the cursor, or new line. One undo would undo the entire document and then they could lose their entire work.

Another approach I thought of (that doesn't solve the problem above) was whenever we create a new branch, we can pickle the current file (I guess in the place where we save user history as well). Later, if the user wants to reset to an old state, they can directly go back to one of the saved file's states by swapping the current file with the saved file and from there they can undo to wherever they wish. I guess this is similar to committing and resetting to a previous commit, but we'll also have the previous commit's redoChain.

aaxu avatar Nov 04 '17 18:11 aaxu

Hmm.. I was thinking about this one day and thought that for people who use a lot of redoes, their tree would have a large number of branches and paths. I was thinking we could have a mini commit feature built into the program. For example:

  • the user can perhaps press CTRL_T or some other key to open a new window, displaying all "commits"/saved histories. These would in actuality be temporary files that we store on the user's disk.
  • the user can create a new "commit" which saves the current file's state (redo history, maybe some other data like bookmarks, etc..) onto disk. They should also be able to add a message along with this commit.
  • the user can also load in any previous "commit" or delete any of them.
  • the user should be able to exit this screen (ESC?). loading a previous commit should also automatically exit this screen and go back to the file.

Not exactly sure how useful this would be, as it's like an in-program version of commits and branches, but it seems like we could make it very use friendly. There is also the option of integrating github support and placing this gui as a layer over it, but then this leaves out files that are not part of a repository.

aaxu avatar Apr 12 '18 07:04 aaxu