aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty/src')
-rw-r--r--alacritty/src/display.rs28
-rw-r--r--alacritty/src/event.rs46
-rw-r--r--alacritty/src/input.rs18
-rw-r--r--alacritty/src/renderer/mod.rs1
-rw-r--r--alacritty/src/url.rs1
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()
}