aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/event.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty/src/event.rs')
-rw-r--r--alacritty/src/event.rs102
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,