Add basic undo in project panel#47091
Conversation
|
We require contributors to sign our Contributor License Agreement, and we don't have @HactarCE on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
--------- Co-authored-by: Cole Miller <cole@zed.dev>
14145f1 to
1cf99e0
Compare
|
I no longer work at Zed, but I'm glad someone picked this up. Thank you so much for continuing this! |
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
|
Hey @marcocondrache 👋 Thanks for opening this. I was looking at #5039 last week to pick it up and see if we can ship it, so it’s great to see you continuing the work from #45008 ! I paired briefly with @cole-miller today, and we’re planning to update Byron/trash-rs to centralize all trashing and restoring logic there. That crate already provides restoration logic, and both Byron/trash-rs#109 and Byron/trash-rs#128 explore returning the actual item that was trashed, for both Linux and macOS, so that it can be restored. With those changes, it seems we’d only be missing restoration support for macOS as well as returning trashed items on Windows. If that goes well, we may update these PR changes accordingly, assuming you’re comfortable with that. Let me know if you’re up for some pairing time 🙂 |
|
Hey @dinocosta, thanks for checking this - I had exactly the same idea. Instead of copying to a temporary folder like in #45008, we can reuse the OS trash and avoid doing the work twice. The current state of the PR already does this (at least on macOS), and I’ve been exploring how to implement it on Linux and Windows as well. I looked at I love pairing sessions, so we can arrange a meeting. |
This reverts commit 705f0d1.
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
dinocosta
left a comment
There was a problem hiding this comment.
Hey @marcocondrache 👋
Thank you so much for continuing the work on this! I've had a chance to review the current state of these changes and leave some comments in the code, where appropriate.
Some feedback isn't particular to the file or code, so I'll leave it here instead:
- We'll probably need to think a little bit more on how we undo the
ProjectPanelOperation::Batchoperation. The current implementation seems to simply pop the operation off the stack and then attempts to undo all the operations within it. However, it seems that, if one of the operations within the batch fails to undo, we halt execution and silently "drop" the remaining operations. I wonder if we'll want to, at least, notify the user of which operations failed. - We still need to explore how we're going to deal with conflicts. For example, right now, if I have a
src/main.rsfile and, through the Project Panel, rename it tosrc/bananas.rsbut then, outside of Zed, create a newsrc/main.rsfile, attempting to undo the rename will silently fail, while also popping the operation from theundo_stack. For the scope of this Pull Request, I believe we only need to care about displaying an error message to the user when undoing an operation fails, possibly with concrete information on what the operation was trying to do, for example, in the case shared above we'd likely want to tell the user that the rename failed because the target file already exists. In a future Pull Request, we might want to explore how to actually provide conflict resolution steps to the user, maybe something as simple as allowing the user to skip the operation or keeping track of the failed operations so we can retry, after the user manually resolves the conflict. - Having an "Undo" option option to the right-click menu used in the project panel might also make it easier to discover that this feature exists.
- Should be disable in case
undo_stack.is_empty()istrue - I might also, in the future, discuss with our design team if there's any icon/indicator/button we want to add for this, to make it easier for folks to know it exists
- Should be disable in case
- I feel like maybe creating a new
crates/project_panel/src/undo.rsmodule might be a good idea, so we can centralize all this undo/redo system logic and implementation there, especially sincecrates/project_panel/src/project_panel.rsis already ~6500 lines long.
Hope this helps! Let me know if you have any question or suggestion regarding any of the points or if there's something you'd prefer we pair on. Thanks! 🙂
e2c9d9e to
4a31d70
Compare
|
@dinocosta thanks a lot for reviewing this!
|
undo Update the undo for the `ProjectPanelOperation::Create` operation in order to trash the file instead of completely deleting. With the current plans, when we eventually introduce the redo functionality, this is the outcome the user should expect and, for the time being, it's less "agressive" to just trash the file. Otherwise one can easily see a scenario where an user creates a file while in the project panel, starts writing code on it, maybe updating the codebase to actually use code from that and then, by accident, focus back on the project panel and uses the undo keybinding, accidentally deleting all of its work. As such, it's better to just trash the file for now.
* Update `project_panel::undo::UndoManager::revert_operation` in order
to return a vector of errors. This way we can determine whether
undoing the operation failed and return multiple errors in the case of
a `ProjectPanelOperation::Batch`.
* Introduce `project_panel::undo::UndoManager::show_errors` to display a
workspace notification with all of the errors that originated when
attempting to undo a project panel operation.
* Since we need to be aware of the workspace in order to be able to
display a workspace notification, `UndoManager::workspace` has also
been introduced
Since `UndoManager::workspace` now exists in order for the implementation to be able to show error notifications, we can access the project trough `Workspace::project`, so this commit removes the `UndoManager::project` field and updates implementation accordingly.
* Update `project_panel::undo::UndoManager::stack` to be a `VecDeque`
instead of a `circular_buffer::CircularBuffer`, as Rust's standard
library already provides a structure for a ring buffer
* In theory, using `VecDeque` should also make it easier to implement
the redo functionality in the future, as we can simply keep a
pointer to the index in the vector where the user's state currently
is, and any undoing means reverting the opration and decreasing the
cursor, while redo is performing the action and advancing the cursor
* Introduce `project_panel::undo::UndoManager::new_with_limit` in order
for us to be able to leverage it in tests
* Even though all of the tests in the `project_panel` crate live in
the `project_panel::project_panel_tests` module, I've added a
`UndoManager` specific test to `project_panel::undo::test`, but we
can always move it to the `project_panel::project_panel_tests`
module in the future, if necessary, otherwise I think this is
cleaner
Update `UndoManager::record` to now take a single operation while `record_batch` handles multiple, normalising them into a `Batch` or unwrapping when only one is provided. This removes the ambiguous `IntoIterator` API and the `ProjectPanelOperation::batch` smart constructor.
Batch operations are now reverted sequentially rather than in parallel via `join_all`, and in reverse order to handle dependencies. For example, if the list of batched operations is one to create the `src/` folder and another to create the `src/main.rs`, if one tries to trash the `src/` folder first, it would fail on a non-empty directory.
dinocosta
left a comment
There was a problem hiding this comment.
Hey @marcocondrache ! 👋
Thank you so much for tackling the provided feedback, and sorry for the late reply! I ended up pushing some changes, should be pretty easy for you to review what I changed based on each commit's message but here's a quick overview:
- Update the revert implementation for
Createin order to actually trash and not delete the file - Implemented error notifications when undoing a project panel operation fails
- Refactored
UndoManager::stackto usestd::colllections::VecDequeinstead ofcircular_buffer::CircularBuffer- Since Rust's standard library already provides a structure to implement a ring buffer, I though we could use that instead, only downside is that we need to be the ones ensuring that we respect the operations limit, but that seems okay
- I believe this will also make it easier to implement redo support, as we could easily keep track of a cursor/index in the vector, such that, undoing an operation moves the decreases the cursor and redoing simply increases the cursor. Any new actions would simply be inserted at the current cursor position, discarding any operations that existed from the cursor to the stack's end
Feel free to take a look at the changes! I'm also organizing next steps and will update you as soon as possible 😀
Introduce a new `ProjectPanelUndoRedoFeatureFlag` feature flag that controls whether the undo/redo system is enabled for the project panel, namely whether the "Undo" context menu item as well as the `Undo` action handler are enabled.
- Add `project_panel::undo::UndoManager` with a bounded operation stack to track and revert project panel operations - Support undoing file and directory creation, renaming, moving, pasting and drag-and-drop operations - Revert batch operations sequentially in reverse order to handle dependencies between them - Show an error notification when one or more undo operations fail - Add "Undo" entry to the project panel context menu, disabled when there is nothing to undo - Gate the feature behind the `project-panel-undo-redo` feature flag Ref: zed-industries#5039 Release Notes: - N/A --------- Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: dino <dinojoaocosta@gmail.com>
- Add `project_panel::undo::UndoManager` with a bounded operation stack to track and revert project panel operations - Support undoing file and directory creation, renaming, moving, pasting and drag-and-drop operations - Revert batch operations sequentially in reverse order to handle dependencies between them - Show an error notification when one or more undo operations fail - Add "Undo" entry to the project panel context menu, disabled when there is nothing to undo - Gate the feature behind the `project-panel-undo-redo` feature flag Ref: zed-industries#5039 Release Notes: - N/A --------- Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: dino <dinojoaocosta@gmail.com>
- Add `project_panel::undo::UndoManager` with a bounded operation stack to track and revert project panel operations - Support undoing file and directory creation, renaming, moving, pasting and drag-and-drop operations - Revert batch operations sequentially in reverse order to handle dependencies between them - Show an error notification when one or more undo operations fail - Add "Undo" entry to the project panel context menu, disabled when there is nothing to undo - Gate the feature behind the `project-panel-undo-redo` feature flag Ref: zed-industries#5039 Release Notes: - N/A --------- Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: dino <dinojoaocosta@gmail.com>
- Add `project_panel::undo::UndoManager` with a bounded operation stack to track and revert project panel operations - Support undoing file and directory creation, renaming, moving, pasting and drag-and-drop operations - Revert batch operations sequentially in reverse order to handle dependencies between them - Show an error notification when one or more undo operations fail - Add "Undo" entry to the project panel context menu, disabled when there is nothing to undo - Gate the feature behind the `project-panel-undo-redo` feature flag Ref: zed-industries#5039 Release Notes: - N/A --------- Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: dino <dinojoaocosta@gmail.com>
Initial part for #5039
Continues work from #45008. The author is no longer assigned to the issue, so I’m assuming it’s unclaimed. Please close this if that’s not correct.
Release Notes: