Move the cursor on search in Terminal if ViMode is active (#33305)

Currently, the terminal search function doesn't work well with ViMode.
It matches the search terms, scrolls the active match in the view, but
it doesn't move the cursor to the match, which makes it useless for
navigating the scrollback in vimode.

With this improvement, if a user activates ViMode before the search Zed
moves the cursor to the active search terms. So, when the search dialog
is dismissed the cursor is places on the latest active search term and
it's possible to navigate the scrollback via ViMode using this place as
the starting point.


https://github.com/user-attachments/assets/63325405-ed93-4bf8-a00f-28ded5511f31

Release Notes:

- Improved the search function in the terminal when ViMode is activated
This commit is contained in:
Aleksei Gusev 2025-08-14 00:45:50 +03:00 committed by GitHub
parent 09e90fb023
commit 665006c414
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 4 deletions

View file

@ -167,6 +167,7 @@ enum InternalEvent {
// Vi mode events
ToggleViMode,
ViMotion(ViMotion),
MoveViCursorToAlacPoint(AlacPoint),
}
///A translation struct for Alacritty to communicate with us from their event loop
@ -972,6 +973,10 @@ impl Terminal {
term.scroll_to_point(*point);
self.refresh_hovered_word(window);
}
InternalEvent::MoveViCursorToAlacPoint(point) => {
term.vi_goto_point(*point);
self.refresh_hovered_word(window);
}
InternalEvent::ToggleViMode => {
self.vi_mode_enabled = !self.vi_mode_enabled;
term.toggle_vi_mode();
@ -1100,12 +1105,21 @@ impl Terminal {
pub fn activate_match(&mut self, index: usize) {
if let Some(search_match) = self.matches.get(index).cloned() {
self.set_selection(Some((make_selection(&search_match), *search_match.end())));
self.events
.push_back(InternalEvent::ScrollToAlacPoint(*search_match.start()));
if self.vi_mode_enabled {
self.events
.push_back(InternalEvent::MoveViCursorToAlacPoint(*search_match.end()));
} else {
self.events
.push_back(InternalEvent::ScrollToAlacPoint(*search_match.start()));
}
}
}
pub fn clear_matches(&mut self) {
self.matches.clear();
self.set_selection(None);
}
pub fn select_matches(&mut self, matches: &[RangeInclusive<AlacPoint>]) {
let matches_to_select = self
.matches