Skip to content

project_panel: Initial redo support#51970

Closed
dinocosta wants to merge 5 commits into
mainfrom
5039-project-panel-redo
Closed

project_panel: Initial redo support#51970
dinocosta wants to merge 5 commits into
mainfrom
5039-project-panel-redo

Conversation

@dinocosta
Copy link
Copy Markdown
Member

Context

These changes continue the work started on #47091 by introducing support for redoing actions in the Project Panel, namely through the Redo action.

How to Review

Although the order of the commits should help in reviewing these changes, here's a quick breakdown with the order I recommend reviewing these changes:

  • Introduced project_panel::undo::UndoManager::cursor which allows tracking the position in the history of operations where the user currently is
  • From the cursor we can now move the cursor either backwards on undo, or forwards on redo
  • Introduced a new project_panel::Redo action, as well as a listener for this action
  • Updated default platform's keymap to map project_panel::Redo
  • Introduced support for redoing both ProjectPanelOperation::Rename and ProjectPanelOperation::Batch. Support for redoing ProjectPanelOperation::Create will come in a future Pull Request, once we add the ability to track the trashed file's location

Self-Review Checklist

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content is consistent with the UI/UX checklist
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • N/A

* Introduce `project_panel::Redo` action
* Add the necessary handler for the `project_panel::Redo` action
    * For the time being, the redo implementation doesn't actually redo
      anything at all as that will be added in a future commit, this one
      was more focused on actually shipping the cursor-based tracking of
      undo history in order to support redoing operations
* Introduce `UndoManager::cursor` in order to allow tracking where the
  current position is in the undo history, which also makes it easier to
  re-use the undo history for redoing operations, without the need to
  introduce another data structure to hold the redo history
* Update default platform keymaps to include a binding for
  `project_panel::Redo`
* Update `project_panel::undo::UndoManager::redo` to support redoing
  rename operations. Support for other opeations will come in future
  commits
* Extract rename logic into `project_panel::undo::UndoManager::rename`
  as it can be used both when undoing and redoing rename operations
* Refactor `project_panel::undo::UndoManager::show_errors` to expect the
  title as an argument, so that it can be used for both undo and redo
  errors
* Update `project_panel::project_panel_tests::test_undo_rename` to
  `project_panel::project_panel_tests::test_undo_redo_rename` as it now
  also tests redoing rename operations
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Mar 19, 2026
@dinocosta dinocosta self-assigned this Mar 19, 2026
@github-actions
Copy link
Copy Markdown

📏 PR Size: 1768 lines changed (size/XL)

Please note: this PR exceeds the 400 LOC soft limit.

  • Consider splitting into separate PRs if the changes are separable
  • Ensure the PR description includes a guided tour in the "How to Review" section so reviewers know where to start

✅ "How to Review" section appears to include guidance — thank you!

@github-actions github-actions Bot added the large-pr Automation related label for detecting large contributor PRs label Mar 19, 2026
@zed-community-bot zed-community-bot Bot added the staff Pull requests authored by a current member of Zed staff label Mar 19, 2026
@zed-codeowner-coordinator zed-codeowner-coordinator Bot requested a review from a team March 19, 2026 19:43
@dinocosta dinocosta changed the title Initial support for redoing operations in Project Panel project_panel: Initial redo support Mar 19, 2026
@dinocosta dinocosta linked an issue Mar 19, 2026 that may be closed by this pull request
* Update `project_panel::undo::UndoManager::redo_operation` in order to
  suport redoing `ProjectPanelOperation::Batch` operations.
* Introduce `project_panel::undo::test::build_rename_operation` helper
  function
* Add tests for ensuring that redoing a batch of operations works as
  expected
@dinocosta dinocosta force-pushed the 5039-project-panel-redo branch from c022997 to e97db03 Compare March 20, 2026 10:35
@dinocosta dinocosta marked this pull request as draft March 23, 2026 12:33
@dinocosta
Copy link
Copy Markdown
Member Author

Moving this back to Draft as I've noticed, while working on adding redo support to file creation operations, that it makes more sense to have separate stacks for the undo and redo operations.

For example, when a new file is created through the Project Panel, we record that as a ProjectPanelOperation::Create, where we simply track the file's location (which includes its name). However, when undoing, we'd want to keep track of the TrashedEntry, as undoing a Create operation simply means, at the moment, trashing that file.

If we were to keep all of this tracking logic in a single VecDeque, that would mean adding a new Option<TrashedEntry> field to the UndoManager::history, as well as having to mutate existing operations in the history, which can be a bit messy.

As such, I'm now working on updating this approach such that, undoing a Create operation returns the inverse operation, probably something like Restore.

Update fields for both `project_panel::undo::Rename` and
`project_panel::PasteTask` from `old_path` and `new_path` to `from` and
`to` to make it a little bit easier to reason about when undoing and
redoing.
Refactor how `project_panel::undo::UndoManager` supports redo
operations. The initial plan before this commit was to have a single
`VecDeque` complemented by a cursor, where undoing an operation meant
decreasing the cursor, and redoing meant increasing the cursor.

That works fine for almost all cases but, in the particular case of a
`Create` or `Trash` operation, we'll eventually need to keep track of
the trashed entry when we wish to redo a `Create` operation, or undo a
`Trash` operation.

As such, this commit re-introduces the idea of using two different
stacks, one for the list of operations to undo and one for the list of
operations to redo, namely
`project_panel::undo::UndoManager::undo_stack` and
`project_panel::undo::UndoManager::redo_stack`.

It also updates the overall approach such that:

1. When recording an operation, we invert it and push that to the undo
   stack
2. When undoing, we execute the most recent operation in the undo stack
   and push its inverse to the redo stack
3. When redoing, we execute the most recent operation in the redo stack
   and push its inverse to the undo stack

This makes it so that `UndoManager` more or less only needs to know
which operation to execute and where to push the resulting operation,
allowing us to get rid of `UndoManager::undo_operation` and
`UndoManager::redo_operation` specific methods.

Unfortunately, one thing that was lost in this refactor is that, right
now, we early-return in the `Batch` operation, as soon as a single
operation fails, so we'll always only show one message, we might want to
revisit this later.
@github-actions github-actions Bot added Size XL and removed Size L labels Mar 23, 2026
@dinocosta
Copy link
Copy Markdown
Member Author

I’m going to close this in favor of #53311 for a couple of reasons:

  • That pull request refactors most of the ‎⁠UndoManager⁠’s undo and redo implementation, and all of those changes were done while pairing, so we know at least two people have thought them through.
  • As mentioned in the previous comment, the issue doesn’t actually require separate stacks. We’ve been able to keep a single ‎⁠VecDeque⁠ plus a cursor. The key change is that we now separate the operation (the intent) from the change (the result of running the operation), and we only record the change. That makes it possible to derive the operation needed to revert it.

So even though that pull request is larger and takes a different approach, it’s in a much better place, especially since it was shaped through pairing 🙂

@dinocosta dinocosta closed this Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement large-pr Automation related label for detecting large contributor PRs staff Pull requests authored by a current member of Zed staff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot undo actions in the project panel

1 participant