diff options
Diffstat (limited to 'alacritty/src')
-rw-r--r-- | alacritty/src/display.rs | 28 | ||||
-rw-r--r-- | alacritty/src/event.rs | 46 | ||||
-rw-r--r-- | alacritty/src/input.rs | 18 | ||||
-rw-r--r-- | alacritty/src/renderer/mod.rs | 1 | ||||
-rw-r--r-- | alacritty/src/url.rs | 1 |
5 files changed, 70 insertions, 24 deletions
diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs index 6d683336..af21001e 100644 --- a/alacritty/src/display.rs +++ b/alacritty/src/display.rs @@ -27,7 +27,7 @@ use crossfont::{self, Rasterize, Rasterizer}; use alacritty_terminal::event::{EventListener, OnResize}; use alacritty_terminal::index::{Column, Direction, Point}; use alacritty_terminal::selection::Selection; -use alacritty_terminal::term::{RenderableCell, SizeInfo, Term, TermMode}; +use alacritty_terminal::term::{SizeInfo, Term, TermMode}; use alacritty_terminal::term::{MIN_COLS, MIN_SCREEN_LINES}; use crate::config::font::Font; @@ -437,7 +437,13 @@ impl Display { mods: ModifiersState, search_state: &SearchState, ) { - let grid_cells: Vec<RenderableCell> = terminal.renderable_cells(config).collect(); + // Convert search match from viewport to absolute indexing. + let search_active = search_state.regex().is_some(); + let viewport_match = search_state + .focused_match() + .and_then(|focused_match| terminal.grid().clamp_buffer_range_to_visible(focused_match)); + + let grid_cells = terminal.renderable_cells(config, !search_active).collect::<Vec<_>>(); let visual_bell_intensity = terminal.visual_bell.intensity(); let background_color = terminal.background_color(); let cursor_point = terminal.grid().cursor.point; @@ -471,7 +477,21 @@ impl Display { self.renderer.with_api(&config.ui_config, config.cursor, &size_info, |mut api| { // Iterate over all non-empty cells in the grid. - for cell in grid_cells { + for mut cell in grid_cells { + // Invert the active match in vi-less search. + let cell_point = Point::new(cell.line, cell.column); + if cell.is_match + && viewport_match + .as_ref() + .map_or(false, |viewport_match| viewport_match.contains(&cell_point)) + { + let colors = config.colors.search.focused_match; + let match_fg = colors.foreground().color(cell.fg, cell.bg); + cell.bg = colors.background().color(cell.fg, cell.bg); + cell.fg = match_fg; + cell.bg_alpha = 1.0; + } + // Update URL underlines. urls.update(size_info.cols(), &cell); @@ -525,7 +545,7 @@ impl Display { } if let Some(message) = message_buffer.message() { - let search_offset = if search_state.regex().is_some() { 1 } else { 0 }; + let search_offset = if search_active { 1 } else { 0 }; let text = message.text(&size_info); // Create a new rectangle for the background. diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 20f087c3..c1f81300 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -9,6 +9,7 @@ use std::fs; use std::fs::File; use std::io::Write; use std::mem; +use std::ops::RangeInclusive; use std::path::PathBuf; #[cfg(not(any(target_os = "macos", windows)))] use std::sync::atomic::Ordering; @@ -94,6 +95,9 @@ pub struct SearchState { /// Search origin in viewport coordinates relative to original display offset. origin: Point, + + /// Focused match during active search. + focused_match: Option<RangeInclusive<Point<usize>>>, } impl SearchState { @@ -110,6 +114,11 @@ impl SearchState { pub fn direction(&self) -> Direction { self.direction } + + /// Focused match during vi-less search. + pub fn focused_match(&self) -> Option<&RangeInclusive<Point<usize>>> { + self.focused_match.as_ref() + } } impl Default for SearchState { @@ -118,6 +127,7 @@ impl Default for SearchState { direction: Direction::Right, display_offset_delta: 0, origin: Point::default(), + focused_match: None, regex: None, } } @@ -209,7 +219,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon selection.update(absolute_point, side); // Move vi cursor and expand selection. - if self.terminal.mode().contains(TermMode::VI) { + if self.terminal.mode().contains(TermMode::VI) && !self.search_active() { self.terminal.vi_mode_cursor.point = point; selection.include_all(); } @@ -385,6 +395,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon let num_lines = self.terminal.screen_lines(); let num_cols = self.terminal.cols(); + self.search_state.focused_match = None; self.search_state.regex = Some(String::new()); self.search_state.direction = direction; @@ -393,9 +404,6 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon 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), @@ -420,9 +428,15 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon fn cancel_search(&mut self) { self.terminal.cancel_search(); - // Recover pre-search state in vi mode. if self.terminal.mode().contains(TermMode::VI) { + // Recover pre-search state in vi mode. self.search_reset_state(); + } else if let Some(focused_match) = &self.search_state.focused_match { + // Create a selection for the focused match. + let start = self.terminal.grid().clamp_buffer_to_visible(*focused_match.start()); + let end = self.terminal.grid().clamp_buffer_to_visible(*focused_match.end()); + self.start_selection(SelectionType::Simple, start, Side::Left); + self.update_selection(end, Side::Right); } self.exit_search(); @@ -431,8 +445,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon #[inline] fn push_search(&mut self, c: char) { if let Some(regex) = self.search_state.regex.as_mut() { - // Prevent previous search selections from sticking around when not in vi mode. if !self.terminal.mode().contains(TermMode::VI) { + // Clear selection so we do not obstruct any matches. self.terminal.selection = None; } @@ -533,8 +547,8 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.search_reset_state(); self.terminal.cancel_search(); - // Restart search without vi mode to clear the search origin. if !self.terminal.mode().contains(TermMode::VI) { + // Restart search without vi mode to clear the search origin. self.start_search(self.search_state.direction); } } else { @@ -554,6 +568,9 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.terminal.scroll_display(Scroll::Delta(self.search_state.display_offset_delta)); self.search_state.display_offset_delta = 0; + // Clear focused match. + self.search_state.focused_match = None; + // Reset vi mode cursor. let mut origin = self.search_state.origin; origin.line = min(origin.line, self.terminal.screen_lines() - 1); @@ -586,12 +603,11 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { } 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); } + // Update the focused match. + self.search_state.focused_match = Some(regex_match); + // Store number of lines the viewport had to be moved. let display_offset = self.terminal.grid().display_offset(); self.search_state.display_offset_delta += old_offset - display_offset as isize; @@ -611,13 +627,16 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { TimerId::DelayedSearch, ); } + + // Clear focused match. + self.search_state.focused_match = None; }, } self.search_state.regex = Some(regex); } - /// Close the search bar. + /// Cleanup the search state. fn exit_search(&mut self) { // Move vi cursor down if resize will pull content from history. if self.terminal.history_size() != 0 @@ -630,6 +649,9 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.display_update_pending.dirty = true; self.search_state.regex = None; self.terminal.dirty = true; + + // Clear focused match. + self.search_state.focused_match = None; } /// Get the absolute position of the search origin. diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 9c75753a..348db610 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -360,14 +360,13 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { #[inline] pub fn mouse_moved(&mut self, position: PhysicalPosition<f64>) { - let search_active = self.ctx.search_active(); let size_info = self.ctx.size_info(); let (x, y) = position.into(); let lmb_pressed = self.ctx.mouse().left_button_state == ElementState::Pressed; let rmb_pressed = self.ctx.mouse().right_button_state == ElementState::Pressed; - if !self.ctx.selection_is_empty() && (lmb_pressed || rmb_pressed) && !search_active { + if !self.ctx.selection_is_empty() && (lmb_pressed || rmb_pressed) { self.update_selection_scrolling(y); } @@ -405,9 +404,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { // Don't launch URLs if mouse has moved. self.ctx.mouse_mut().block_url_launcher = true; - if (lmb_pressed || rmb_pressed) - && (self.ctx.modifiers().shift() || !self.ctx.mouse_mode()) - && !search_active + if (lmb_pressed || rmb_pressed) && (self.ctx.modifiers().shift() || !self.ctx.mouse_mode()) { self.ctx.update_selection(point, cell_side); } else if inside_text_area @@ -600,7 +597,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { self.ctx.update_selection(point, cell_side); // Move vi mode cursor to mouse click position. - if self.ctx.terminal().mode().contains(TermMode::VI) { + if self.ctx.terminal().mode().contains(TermMode::VI) && !self.ctx.search_active() { self.ctx.terminal_mut().vi_mode_cursor.point = point; } } @@ -635,7 +632,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { }; // Move vi mode cursor to mouse click position. - if self.ctx.terminal().mode().contains(TermMode::VI) { + if self.ctx.terminal().mode().contains(TermMode::VI) && !self.ctx.search_active() { self.ctx.terminal_mut().vi_mode_cursor.point = point; } } @@ -791,7 +788,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { }; self.ctx.window_mut().set_mouse_cursor(new_icon); - } else if !self.ctx.search_active() { + } else { match state { ElementState::Pressed => { self.process_mouse_bindings(button); @@ -963,6 +960,11 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> { /// The provided mode, mods, and key must match what is allowed by a binding /// for its action to be executed. fn process_mouse_bindings(&mut self, button: MouseButton) { + // Ignore bindings while search is active. + if self.ctx.search_active() { + return; + } + let mods = *self.ctx.modifiers(); let mode = *self.ctx.terminal().mode(); let mouse_mode = self.ctx.mouse_mode(); diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index f628d24f..b347556d 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -958,6 +958,7 @@ impl<'a> RenderApi<'a> { bg_alpha, fg, bg: bg.unwrap_or(Rgb { r: 0, g: 0, b: 0 }), + is_match: false, }) .collect::<Vec<_>>(); diff --git a/alacritty/src/url.rs b/alacritty/src/url.rs index f3f60dd3..5d35667d 100644 --- a/alacritty/src/url.rs +++ b/alacritty/src/url.rs @@ -207,6 +207,7 @@ mod tests { bg: Default::default(), bg_alpha: 0., flags: Flags::empty(), + is_match: false, }) .collect() } |