helix-editor / helix

A post-modern modal text editor.
https://helix-editor.com
Mozilla Public License 2.0
31.84k stars 2.35k forks source link

Undo tree UI #1075

Open NNBnh opened 2 years ago

NNBnh commented 2 years ago

Come from Kakoune, one of the feature that many feel missing is Undo tree, from Kakoune wiki:

Kakoune keeps track of every modification you make to a buffer.

It does this bookkeeping in a non linear way: it means that if you undo a few changes and then decide to make a new one, it will create a branch in the history tree.

Let's see how it works through a concrete example.

... (Read more)

This seem kinda hard, maybe implement this in the far future.

archseer commented 2 years ago

We have an undo tree internally with support for :earlier :later. We just don't have a good way to visualize the tree

sudormrfbin commented 2 years ago

Can we keep this issue open for implementing a UI for it ?

pickfire commented 2 years ago

But I think we don't have a shortcut for it. Like g- and g+ in vim. Would be good to have something easily accessible.

NNBnh commented 2 years ago

But I think we don't have a shortcut for it. Like g- and g+ in vim. Would be good to have something easily accessible.

We could map it to gu undo_tree and gU redo_tree to be more consistent with u undo and U redo

But should we do it like Vim/Kakoune or should we make something like Spaceu undotree_picker ?

heliostatic commented 2 years ago

Could we use the infobox to display the tree? e.g. https://github.com/helix-editor/helix/pull/980

It would require making the infobox interactable, however...

sudormrfbin commented 2 years ago

It would be better to have a tree widget component which can properly handle the structure and associated keybinds, and plus it can be reused for a file tree (#200).

NNBnh commented 2 years ago

It would be better to have a tree widget component which can properly handle the structure and associated keybinds, and plus it can be reused for a file tree (#200).

Agree! i suggest we redesign the picker UI:

The current picker is pretty fancy, too fancy actually. Everything is contained inside a box in the center of the window which block the whole view of the buffer and also make the picker look clutter. We should expand the picker to the whole window:

from this:

Screenshot_2021-11-25_11-19-56

to this:

  ./           ┃ 1 ┃ print("Hello, World!")
  ├╴foo/       ┃ 2 ┃
> │ ├╴1.py     ┃ 3 ┃
  │ └╴2.py     ┃ 4 ┃
  ├╴bar/       ┃ 5 ┃
  └╴README.md  ┃ 6 ┃
               ┃ 7 ┃
               ┃ 8 ┃
░ NOR ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1:1 ░
file picker:▁                               [3/3]

by:

  1. Move the picker prompt to the bottom, reusing the original prompt and also display the picker name to the left.
  2. Also move the match counter to the right of the original prompt.
  3. Move the list to the left of the window (not buffer), took 1/3 or 1/4 space of the window.
  4. Move the whole preview to the current buffer.

Navigate the picker should be the same (using UP, DOWN and ENTER), if the pointer focus on a directory (e.g: dir/) user can press ENTER to expand/fold it back.

Bonus: The user could keep the picker on the screen all the time, this should close #200.

archseer commented 2 years ago

I disagree with this / this should be split into two separate issues.

The current picker is pretty fancy, too fancy actually.

It's the most minimal UI we could implement without adding a full file explorer with lots of state (which is your proposal, essentially an embedded nnn -- we have to track multiple tree levels and there's different sets of behavior depending on if you're expanding a directory or opening a file).

I'd like to keep the default interface simple and clutter free and discourage using a file tree; helix is not vscode and it's best to pair it with a terminal file manager like nnn if a file tree hierarchy is desired.

I agree that we could visualize the undo tree though.

matu3ba commented 2 years ago

Just adding my thoughts on undo files tree: Unfortunately undo files dont track changes between files, ie if one function or code part is refactored to another file.

Do you believe this is feasible, ideally on treesitter-based level? The configuration logic would look like this

Functionality could work like this

From briefly thinking this through, this has no fundamental limitation that does not occur with the usual approach besides added complexity for copy-paste besides restricting content to occur exactly in one register or adding complexity to resolve what content moved into which register (think of inserting and copying into temporary buffers etc). Unclear to me would be, how efficient and accurate tracking of changes from external refactoring tools could work. Ideally, those tools can split their changes into diff files.

Do you happen to know, if pijul allows tracking changes at statement level or if anyone wrote a formalization on how this could work? Ideally there would be tooling to encode commits per statement and group them, so the users dont have commit bloat.

Conflating and removing redundant editings to retrieve the relevant semantic changes can then be done in a separate pass.

heliostatic commented 2 years ago

Could this use the tree work in #2377 ?

matu3ba commented 1 year ago

The handmande networks wishlist has code-aware CVS https://github.com/HandmadeNetwork/wishlist/discussions/5, which is essentially structured editing (version control system), which is essentially a language-tailored form of ropes + tracking+resolving their changes.

See "Typed Image-based Programming with Structure Editing" by Edwards and Petricek linked on https://alarmingdevelopment.org/?p=1570 and the video presentation + this nice explanation what ropes are https://blog.jetbrains.com/fleet/2022/02/fleet-below-deck-part-ii-breaking-down-the-editor/ to connect the dots.

It would be obviously nice, if projects like https://www.shadaj.me/writing/introducing-rust-sitter/ come up with better performance of the parser, rather poorly scaling treesitter query system (qeries are rather dumb and dont utilize caching/previous qeries etc) and an API to combine semantic information.

muja commented 1 year ago

Until this is implemented for those that need very granular overview over their edit tree, could we add an option that undo's are memorized in the history so when making an edit after a few undos (creating a new branch), undoing will revert the edit and then the undos. I think here it's explained clearly: https://github.com/zaboople/klonk/blob/master/TheGURQ.md

Somebody also built a crate for that: https://docs.rs/undo_2

The option could be called something like recycleable_undos or whatever. The history "tree-editor" could be implemented independently of course and would be separate from this.

hbuxiaofei commented 2 months ago

I implemented tree-view with two solutions.