vim: Restore cursor position when dismissing buffer search#47732
vim: Restore cursor position when dismissing buffer search#47732ConradIrwin merged 2 commits intozed-industries:mainfrom
Conversation
Fixes zed-industries#8048 When vim search is dismissed with Escape, the cursor now returns to its original position instead of jumping to the first match. The fix leverages the focused() callback in vim.rs which is called when the editor regains focus after the search bar is dismissed. It checks if prior_selections were saved when search started and restores them if the search bar is now dismissed (indicating Escape was pressed, not Enter). Test plan: - Added test_search_dismiss_restores_cursor - Added test_search_dismiss_restores_cursor_no_matches - All 455 vim tests pass
|
Thanks for this! I'm not super happy with this living in the focused handler, but it does seem to work. There's an odd edge case:
I don't think that's a deal breaker per-se; but it's indicative of the structure of the code not quite matching the problem. Do you have other ideas for how we could structure this to be less intrusive? |
|
Thanks for the review! I dug into the architecture to find a cleaner solution. The ProblemMy
Recommended Solution: Add
|
|
thanks. let's try that and see if it works. |
|
Implemented the Clarification on the edge case: In my earlier comment, I incorrectly claimed that the The fix now addresses this properly:
This cleanly separates concerns:
Added a test that verifies the edge case: opening search, focusing editor while search is open, then dismissing—cursor stays at the match location rather than being restored. All 456 vim tests pass. |
|
Thanks |
Restructure the search dismiss cursor restoration to use an explicit Event::Dismissed pattern instead of checking state in the focused() handler. Changes: - Add Event::Dismissed to BufferSearchBar, emitted when search is dismissed - Subscribe to this event in vim's search() to restore prior_selections - In focused(), clear prior_selections if editor gains focus while search is still open (handles the edge case where user clicks in editor before dismissing) - Add test for the edge case: clicking in editor then dismissing should not restore cursor to original position This separates concerns more cleanly: - focused(): "User navigated while search open → clear saved position" - Dismissed subscription: "Search dismissed → restore saved position" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Head branch was pushed to by a user without write access
8918858 to
d335841
Compare
Fixes #8048
Summary
In vim mode, pressing Escape to dismiss the buffer search now correctly restores the cursor to its original position, rather than leaving it at the first match.
Problem
When using vim's
/command to search:/to open search, types a queryThis breaks vim parity where Escape should cancel the search and restore cursor position.
Solution
The fix leverages the
focused()callback invim.rs, which is called when the editor regains focus after the search bar is dismissed.Key insight: When search starts via
/, the cursor position is saved inSearchState.prior_selections. When search is submitted with Enter,search_submit()drains these selections. But when search is dismissed with Escape, they remain.So in
focused(), if:prior_selectionsis non-empty, ANDis_dismissed()returns true...then we know the user dismissed the search (Escape) rather than submitted it (Enter), and we restore the cursor.
Why not handle
buffer_search::Dismissdirectly?The initial approach tried to register a vim handler for the
Dismissaction. This didn't work because when Escape is pressed, the search bar (which has focus) handles theCancelaction internally and calls itsdismiss()method directly—it doesn't dispatchDismissthrough the action system. The vim handler registered on the editor was never invoked.Test Plan
test_search_dismiss_restores_cursor— verifies cursor restoration when search is dismissedtest_search_dismiss_restores_cursor_no_matches— verifies behavior when query has no matches/andcmd-fRelease Notes