diff options
author | Christian Duerr <contact@christianduerr.com> | 2023-09-22 19:49:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-22 21:49:52 +0400 |
commit | a58fb39b68caa34b073f66911c0ac6945f56eac2 (patch) | |
tree | 4e453bd5da22bcd0cc1a3b8ea6246ff17933e3fa | |
parent | e35e5ad14fce8456afdd89f2b392b9924bb27471 (diff) | |
download | alacritty-a58fb39b68caa34b073f66911c0ac6945f56eac2.tar.gz alacritty-a58fb39b68caa34b073f66911c0ac6945f56eac2.zip |
Underline hint matches during selection
This patch underlines the full regex hint match while the keyboard hint
selection is in process.
While it would be possible to color the entire match, this would only
introduce unnecessary configuration options and be too noisy. The
underline matches the mouse highlighting and has a less drastic visual
impact.
Closes #6178.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | alacritty/src/display/content.rs | 57 |
2 files changed, 42 insertions, 16 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 801b059f..40273970 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - The double click threshold was raised to `400ms` - OSC 52 paste ability is now **disabled by default**; use `terminal.osc52` to adjust it - Apply `colors.transparent_background_colors` for selections, hints, and search matches +- Underline full hint during keyboard selection ### Fixed diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs index ec0f4b6a..0849b30a 100644 --- a/alacritty/src/display/content.rs +++ b/alacritty/src/display/content.rs @@ -4,7 +4,7 @@ use std::{cmp, mem}; use alacritty_terminal::ansi::{Color, CursorShape, NamedColor}; use alacritty_terminal::event::EventListener; -use alacritty_terminal::grid::Indexed; +use alacritty_terminal::grid::{Dimensions, Indexed}; use alacritty_terminal::index::{Column, Line, Point}; use alacritty_terminal::selection::SelectionRange; use alacritty_terminal::term::cell::{Cell, Flags, Hyperlink}; @@ -15,7 +15,7 @@ use alacritty_terminal::term::{self, RenderableContent as TerminalContent, Term, use crate::config::UiConfig; use crate::display::color::{List, DIM_FACTOR}; use crate::display::hint::{self, HintState}; -use crate::display::Display; +use crate::display::{Display, SizeInfo}; use crate::event::SearchState; /// Minimum contrast between a fixed cursor color and the cell's background. @@ -34,6 +34,7 @@ pub struct RenderableContent<'a> { config: &'a UiConfig, colors: &'a List, focused_match: Option<&'a Match>, + size: &'a SizeInfo, } impl<'a> RenderableContent<'a> { @@ -74,6 +75,7 @@ impl<'a> RenderableContent<'a> { Self { colors: &display.colors, + size: &display.size_info, cursor: RenderableCursor::new_hidden(), terminal_content, focused_match, @@ -223,18 +225,27 @@ impl RenderableCell { let viewport_start = Point::new(Line(-(display_offset as i32)), Column(0)); let colors = &content.config.colors; let mut character = cell.c; + let mut flags = cell.flags; - if let Some((c, is_first)) = - content.hint.as_mut().and_then(|hint| hint.advance(viewport_start, cell.point)) + let num_cols = content.size.columns(); + if let Some((c, is_first)) = content + .hint + .as_mut() + .and_then(|hint| hint.advance(viewport_start, num_cols, cell.point)) { - let (config_fg, config_bg) = if is_first { - (colors.hints.start.foreground, colors.hints.start.background) + if is_first { + let (config_fg, config_bg) = + (colors.hints.start.foreground, colors.hints.start.background); + Self::compute_cell_rgb(&mut fg, &mut bg, &mut bg_alpha, config_fg, config_bg); + } else if c.is_some() { + let (config_fg, config_bg) = + (colors.hints.end.foreground, colors.hints.end.background); + Self::compute_cell_rgb(&mut fg, &mut bg, &mut bg_alpha, config_fg, config_bg); } else { - (colors.hints.end.foreground, colors.hints.end.background) - }; - Self::compute_cell_rgb(&mut fg, &mut bg, &mut bg_alpha, config_fg, config_bg); + flags.insert(Flags::UNDERLINE); + } - character = c; + character = c.unwrap_or(character); } else if is_selected { let config_fg = colors.selection.foreground; let config_bg = colors.selection.background; @@ -265,7 +276,6 @@ impl RenderableCell { let cell_point = cell.point; let point = term::point_to_viewport(display_offset, cell_point).unwrap(); - let flags = cell.flags; let underline = cell .underline_color() .map_or(fg, |underline| Self::compute_fg_rgb(content, underline, flags)); @@ -440,7 +450,15 @@ impl<'a> Hint<'a> { /// this position will be returned. /// /// The tuple's [`bool`] will be `true` when the character is the first for this hint. - fn advance(&mut self, viewport_start: Point, point: Point) -> Option<(char, bool)> { + /// + /// The tuple's [`Option<char>`] will be [`None`] when the point is part of the match, but not + /// part of the hint label. + fn advance( + &mut self, + viewport_start: Point, + num_cols: usize, + point: Point, + ) -> Option<(Option<char>, bool)> { // Check if we're within a match at all. if !self.matches.advance(point) { return None; @@ -450,15 +468,22 @@ impl<'a> Hint<'a> { let start = self .matches .get(self.matches.index) - .map(|bounds| cmp::max(*bounds.start(), viewport_start)) - .filter(|start| start.line == point.line)?; + .map(|bounds| cmp::max(*bounds.start(), viewport_start))?; // Position within the hint label. - let label_position = point.column.0 - start.column.0; + let line_delta = point.line.0 - start.line.0; + let col_delta = point.column.0 as i32 - start.column.0 as i32; + let label_position = usize::try_from(line_delta * num_cols as i32 + col_delta).unwrap_or(0); let is_first = label_position == 0; // Hint label character. - self.labels[self.matches.index].get(label_position).copied().map(|c| (c, is_first)) + let hint_char = self.labels[self.matches.index] + .get(label_position) + .copied() + .map(|c| (Some(c), is_first)) + .unwrap_or((None, false)); + + Some(hint_char) } } |