Skip to content

fix: derive active worktree from sidebar cursor - #46

Merged
sebasv merged 1 commit into
mainfrom
auto-focus-after-worktree-delete
May 4, 2026
Merged

fix: derive active worktree from sidebar cursor#46
sebasv merged 1 commit into
mainfrom
auto-focus-after-worktree-delete

Conversation

@sebasv

@sebasv sebasv commented May 4, 2026

Copy link
Copy Markdown
Owner

Summary

Adding or removing a worktree updated the sidebar selection but left the main pane showing the previously-active worktree (or the placeholder even when the cursor had moved to a survivor). Sidebar selection (ui.cursor, index-based) and main-pane driver (ui.active_worktree, path-based) were two independent fields that every mutation site had to remember to sync — and several didn't.

This makes the cursor the single source of truth: active_worktree_id() derives from ui.cursor, so navigating in the sidebar always refreshes the main pane. No separate "commit" step needed.

  • remap_worktree_state also remaps the cursor by path, with fallbacks for vanished paths and emptied lists, so reorders and FS events keep the main pane in sync.
  • try_create_worktree_modal lands the cursor on the just-created worktree by path lookup — git lists alphabetically, so the previous "tail of the list" assumption picked the wrong row on macOS.
  • Persistence still uses path identity for cross-session survival: to_persisted derives the path from the cursor; apply_persisted resolves it back to indices.

Test plan

  • cargo test — 142/142 pass, including new tests for cursor remap on reorder, on missing-path fallback, and on emptied-list fallback
  • cargo clippy --all-targets -- -D warnings clean
  • cargo fmt --check clean
  • Manual: add a worktree → cursor lands on it, main pane shows its content immediately
  • Manual: delete a worktree → cursor lands on a sibling, main pane shows the sibling's content
  • Manual: delete the last worktree of a repo → cursor jumps to the parent repo, main pane shows placeholder
  • Manual: arrow-navigate through sidebar → main pane follows in lockstep
  • Manual: persisted active selection survives a restart when the path still exists; gracefully drops when it doesn't

🤖 Generated with Claude Code

Adding or removing a worktree updated the sidebar selection but left the
main pane showing the previously-active worktree (or the placeholder
even when the cursor had moved to a survivor). The two were tracked
independently — `ui.cursor` for sidebar highlight, `ui.active_worktree`
for the main pane — and every mutation site had to remember to sync
them.

Make the cursor the single source of truth: `active_worktree_id()` now
derives from the cursor, so navigating in the sidebar always refreshes
the main pane and there's no separate "commit" step.

- `remap_worktree_state` also remaps the cursor by path now, with
  fallbacks for vanished paths and emptied lists, so reorders and FS
  events keep the main pane in sync.
- `try_create_worktree_modal` lands the cursor on the just-created
  worktree by path lookup — git lists alphabetically, so the previous
  "tail of the list" assumption picked the wrong row on macOS.
- Persistence keeps using path identity for cross-session survival:
  `to_persisted` derives the path from the cursor, `apply_persisted`
  resolves it back to indices.

Co-Authored-By: Claude <noreply@anthropic.com>
@sebasv
sebasv merged commit bdda4e4 into main May 4, 2026
1 check passed
@sebasv
sebasv deleted the auto-focus-after-worktree-delete branch May 4, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant