diff options
-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) } } |