diff options
Diffstat (limited to 'alacritty/src/event.rs')
-rw-r--r-- | alacritty/src/event.rs | 102 |
1 files changed, 75 insertions, 27 deletions
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index eed5624f..f06b818e 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -31,7 +31,7 @@ use font::{self, Size}; use alacritty_terminal::config::LOG_TARGET_CONFIG; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify, OnResize}; use alacritty_terminal::grid::{Dimensions, Scroll}; -use alacritty_terminal::index::{Column, Direction, Line, Point, Side}; +use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side}; use alacritty_terminal::selection::{Selection, SelectionType}; use alacritty_terminal::sync::FairMutex; use alacritty_terminal::term::cell::Cell; @@ -91,8 +91,8 @@ pub struct SearchState { /// Change in display offset since the beginning of the search. display_offset_delta: isize, - /// Vi cursor position before search. - vi_cursor_point: Point, + /// Search origin in viewport coordinates relative to original display offset. + origin: Point, } impl SearchState { @@ -106,7 +106,7 @@ impl Default for SearchState { Self { direction: Direction::Right, display_offset_delta: 0, - vi_cursor_point: Point::default(), + origin: Point::default(), regex: None, } } @@ -142,8 +142,16 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon } fn scroll(&mut self, scroll: Scroll) { + let old_offset = self.terminal.grid().display_offset() as isize; + self.terminal.scroll_display(scroll); + // Keep track of manual display offset changes during search. + if self.search_active() { + let display_offset = self.terminal.grid().display_offset(); + self.search_state.display_offset_delta += old_offset - display_offset as isize; + } + // Update selection. if self.terminal.mode().contains(TermMode::VI) && self.terminal.selection.as_ref().map(|s| s.is_empty()) != Some(true) @@ -339,10 +347,14 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon self.search_state.regex = Some(String::new()); self.search_state.direction = direction; - // Store original vi cursor position as search origin and for resetting. - self.search_state.vi_cursor_point = if self.terminal.mode().contains(TermMode::VI) { + // Store original search position as origin and reset location. + self.search_state.display_offset_delta = 0; + self.search_state.origin = if self.terminal.mode().contains(TermMode::VI) { self.terminal.vi_mode_cursor.point } else { + // Clear search, since it is used as the active match. + self.terminal.selection = None; + match direction { Direction::Right => Point::new(Line(0), Column(0)), Direction::Left => Point::new(num_lines - 2, num_cols - 1), @@ -355,9 +367,6 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon #[inline] fn confirm_search(&mut self) { - // Enter vi mode once search is confirmed. - self.terminal.set_vi_mode(); - // Force unlimited search if the previous one was interrupted. if self.scheduler.scheduled(TimerId::DelayedSearch) { self.goto_match(None); @@ -368,9 +377,6 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon self.terminal.vi_mode_cursor.point.line += 1; } - // Clear reset state. - self.search_state.display_offset_delta = 0; - self.display_update_pending.dirty = true; self.search_state.regex = None; self.terminal.dirty = true; @@ -419,6 +425,29 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon } #[inline] + fn advance_search_origin(&mut self, direction: Direction) { + let origin = self.absolute_origin(); + self.terminal.scroll_to_point(origin); + + // Move the search origin right in front of the next match in the specified direction. + if let Some(regex_match) = self.terminal.search_next(origin, direction, Side::Left, None) { + let origin = match direction { + Direction::Right => *regex_match.end(), + Direction::Left => { + regex_match.start().sub_absolute(self.terminal, Boundary::Wrap, 1) + }, + }; + self.terminal.scroll_to_point(origin); + + let origin_relative = self.terminal.grid().clamp_buffer_to_visible(origin); + self.search_state.origin = origin_relative; + self.search_state.display_offset_delta = 0; + + self.update_search(); + } + } + + #[inline] fn search_direction(&self) -> Direction { self.search_state.direction } @@ -487,10 +516,10 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.search_state.display_offset_delta = 0; // Reset vi mode cursor. - let mut vi_cursor_point = self.search_state.vi_cursor_point; - vi_cursor_point.line = min(vi_cursor_point.line, self.terminal.screen_lines() - 1); - vi_cursor_point.col = min(vi_cursor_point.col, self.terminal.cols() - 1); - self.terminal.vi_mode_cursor.point = vi_cursor_point; + let mut origin = self.search_state.origin; + origin.line = min(origin.line, self.terminal.screen_lines() - 1); + origin.col = min(origin.col, self.terminal.cols() - 1); + self.terminal.vi_mode_cursor.point = origin; // Unschedule pending timers. self.scheduler.unschedule(TimerId::DelayedSearch); @@ -506,19 +535,23 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { // Limit search only when enough lines are available to run into the limit. limit = limit.filter(|&limit| limit <= self.terminal.total_lines()); - // Use original position as search origin. - let mut vi_cursor_point = self.search_state.vi_cursor_point; - vi_cursor_point.line = min(vi_cursor_point.line, self.terminal.screen_lines() - 1); - let mut origin = self.terminal.visible_to_buffer(vi_cursor_point); - origin.line = (origin.line as isize + self.search_state.display_offset_delta) as usize; - // Jump to the next match. let direction = self.search_state.direction; - match self.terminal.search_next(origin, direction, Side::Left, limit) { + match self.terminal.search_next(self.absolute_origin(), direction, Side::Left, limit) { Some(regex_match) => { let old_offset = self.terminal.grid().display_offset() as isize; - self.terminal.vi_goto_point(*regex_match.start()); + if self.terminal.mode().contains(TermMode::VI) { + // Move vi cursor to the start of the match. + self.terminal.vi_goto_point(*regex_match.start()); + } else { + // Select the match when vi mode is not active. + self.terminal.scroll_to_point(*regex_match.start()); + let start = self.terminal.grid().clamp_buffer_to_visible(*regex_match.start()); + let end = self.terminal.grid().clamp_buffer_to_visible(*regex_match.end()); + self.start_selection(SelectionType::Simple, start, Side::Left); + self.update_selection(end, Side::Right); + } // Store number of lines the viewport had to be moved. let display_offset = self.terminal.grid().display_offset(); @@ -544,6 +577,19 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.search_state.regex = Some(regex); } + + /// Get the absolute position of the search origin. + /// + /// This takes the relative motion of the viewport since the start of the search into account. + /// So while the absolute point of the origin might have changed since new content was printed, + /// this will still return the correct absolute position. + fn absolute_origin(&self) -> Point<usize> { + let mut relative_origin = self.search_state.origin; + relative_origin.line = min(relative_origin.line, self.terminal.screen_lines() - 1); + let mut origin = self.terminal.visible_to_buffer(relative_origin); + origin.line = (origin.line as isize + self.search_state.display_offset_delta) as usize; + origin + } } #[derive(Debug, Eq, PartialEq)] @@ -1047,9 +1093,11 @@ impl<N: Notify + OnResize> Processor<N> { // Compute cursor positions before resize. let num_lines = terminal.screen_lines(); let cursor_at_bottom = terminal.grid().cursor.point.line + 1 == num_lines; - let origin_at_bottom = (!terminal.mode().contains(TermMode::VI) - && self.search_state.direction == Direction::Left) - || terminal.vi_mode_cursor.point.line == num_lines - 1; + let origin_at_bottom = if terminal.mode().contains(TermMode::VI) { + terminal.vi_mode_cursor.point.line == num_lines - 1 + } else { + self.search_state.direction == Direction::Left + }; self.display.handle_update( terminal, |