aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/display/mod.rs
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2021-04-13 03:24:42 +0000
committerGitHub <noreply@github.com>2021-04-13 03:24:42 +0000
commit96fc9ecc9a62c8a766da745d05fbe60e6c2e1efe (patch)
tree16e237d750d6c650713b58df98453dc4df16d33a /alacritty/src/display/mod.rs
parent40bcdb11335cc49d4d42694b953be746cb383cb9 (diff)
downloadr-alacritty-96fc9ecc9a62c8a766da745d05fbe60e6c2e1efe.tar.gz
r-alacritty-96fc9ecc9a62c8a766da745d05fbe60e6c2e1efe.tar.bz2
r-alacritty-96fc9ecc9a62c8a766da745d05fbe60e6c2e1efe.zip
Add vi/mouse hint highlighting support
This patch removes the old url highlighting code and replaces it with a new implementation making use of hints as sources for finding matches in the terminal.
Diffstat (limited to 'alacritty/src/display/mod.rs')
-rw-r--r--alacritty/src/display/mod.rs122
1 files changed, 80 insertions, 42 deletions
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index 78220b59..6e40e35c 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -2,6 +2,7 @@
//! GPU drawing.
use std::cmp::min;
+use std::convert::TryFrom;
use std::f64;
use std::fmt::{self, Formatter};
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -27,6 +28,7 @@ use alacritty_terminal::event::{EventListener, OnResize};
use alacritty_terminal::grid::Dimensions as _;
use alacritty_terminal::index::{Column, Direction, Line, Point};
use alacritty_terminal::selection::Selection;
+use alacritty_terminal::term::cell::Flags;
use alacritty_terminal::term::{SizeInfo, Term, TermMode, MIN_COLUMNS, MIN_SCREEN_LINES};
use crate::config::font::Font;
@@ -38,14 +40,13 @@ use crate::display::bell::VisualBell;
use crate::display::color::List;
use crate::display::content::RenderableContent;
use crate::display::cursor::IntoRects;
-use crate::display::hint::HintState;
+use crate::display::hint::{HintMatch, HintState};
use crate::display::meter::Meter;
use crate::display::window::Window;
use crate::event::{Mouse, SearchState};
use crate::message_bar::{MessageBuffer, MessageType};
use crate::renderer::rects::{RenderLines, RenderRect};
use crate::renderer::{self, GlyphCache, QuadRenderer};
-use crate::url::{Url, Urls};
pub mod content;
pub mod cursor;
@@ -58,7 +59,13 @@ mod meter;
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
mod wayland_theme;
+/// Maximum number of linewraps followed outside of the viewport during search highlighting.
+pub const MAX_SEARCH_LINES: usize = 100;
+
+/// Label for the forward terminal search bar.
const FORWARD_SEARCH_LABEL: &str = "Search: ";
+
+/// Label for the backward terminal search bar.
const BACKWARD_SEARCH_LABEL: &str = "Backward Search: ";
#[derive(Debug)]
@@ -164,10 +171,12 @@ impl DisplayUpdate {
pub struct Display {
pub size_info: SizeInfo,
pub window: Window,
- pub urls: Urls,
- /// Currently highlighted URL.
- pub highlighted_url: Option<Url>,
+ /// Hint highlighted by the mouse.
+ pub highlighted_hint: Option<HintMatch>,
+
+ /// Hint highlighted by the vi mode cursor.
+ pub vi_highlighted_hint: Option<HintMatch>,
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
pub wayland_event_queue: Option<EventQueue>,
@@ -331,8 +340,8 @@ impl Display {
hint_state,
meter: Meter::new(),
size_info,
- urls: Urls::new(),
- highlighted_url: None,
+ highlighted_hint: None,
+ vi_highlighted_hint: None,
#[cfg(not(any(target_os = "macos", windows)))]
is_x11,
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -473,8 +482,6 @@ impl Display {
terminal: MutexGuard<'_, Term<T>>,
message_buffer: &MessageBuffer,
config: &Config,
- mouse: &Mouse,
- mods: ModifiersState,
search_state: &SearchState,
) {
// Collect renderable content before the terminal is dropped.
@@ -492,10 +499,6 @@ impl Display {
let metrics = self.glyph_cache.font_metrics();
let size_info = self.size_info;
- let selection = !terminal.selection.as_ref().map(Selection::is_empty).unwrap_or(true);
- let mouse_mode = terminal.mode().intersects(TermMode::MOUSE_MODE)
- && !terminal.mode().contains(TermMode::VI);
-
let vi_mode = terminal.mode().contains(TermMode::VI);
let vi_mode_cursor = if vi_mode { Some(terminal.vi_mode_cursor) } else { None };
@@ -507,18 +510,24 @@ impl Display {
});
let mut lines = RenderLines::new();
- let mut urls = Urls::new();
// Draw grid.
{
let _sampler = self.meter.sampler();
let glyph_cache = &mut self.glyph_cache;
+ let highlighted_hint = &self.highlighted_hint;
+ let vi_highlighted_hint = &self.vi_highlighted_hint;
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
// Iterate over all non-empty cells in the grid.
- for cell in grid_cells {
- // Update URL underlines.
- urls.update(&size_info, &cell);
+ for mut cell in grid_cells {
+ // Underline hints hovered by mouse or vi mode cursor.
+ let point = viewport_to_point(display_offset, cell.point);
+ if highlighted_hint.as_ref().map_or(false, |h| h.bounds.contains(&point))
+ || vi_highlighted_hint.as_ref().map_or(false, |h| h.bounds.contains(&point))
+ {
+ cell.flags.insert(Flags::UNDERLINE);
+ }
// Update underline/strikeout.
lines.update(&cell);
@@ -531,33 +540,9 @@ impl Display {
let mut rects = lines.rects(&metrics, &size_info);
- // Update visible URLs.
- self.urls = urls;
- if let Some(url) = self.urls.highlighted(config, mouse, mods, mouse_mode, selection) {
- rects.append(&mut url.rects(&metrics, &size_info));
-
- self.window.set_mouse_cursor(CursorIcon::Hand);
-
- self.highlighted_url = Some(url);
- } else if self.highlighted_url.is_some() {
- self.highlighted_url = None;
-
- if mouse_mode {
- self.window.set_mouse_cursor(CursorIcon::Default);
- } else {
- self.window.set_mouse_cursor(CursorIcon::Text);
- }
- }
-
if let Some(vi_mode_cursor) = vi_mode_cursor {
- // Highlight URLs at the vi mode cursor position.
- let vi_point = vi_mode_cursor.point;
- let line = (vi_point.line + display_offset).0 as usize;
- if let Some(url) = self.urls.find_at(Point::new(line, vi_point.column)) {
- rects.append(&mut url.rects(&metrics, &size_info));
- }
-
// Indicate vi mode by showing the cursor's position in the top right corner.
+ let vi_point = vi_mode_cursor.point;
let line = (-vi_point.line.0 + size_info.bottommost_line().0) as usize;
self.draw_line_indicator(config, &size_info, total_lines, Some(vi_point), line);
} else if search_state.regex().is_some() {
@@ -671,6 +656,47 @@ impl Display {
self.colors = List::from(&config.ui_config.colors);
}
+ /// Update the mouse/vi mode cursor hint highlighting.
+ pub fn update_highlighted_hints<T>(
+ &mut self,
+ term: &Term<T>,
+ config: &Config,
+ mouse: &Mouse,
+ modifiers: ModifiersState,
+ ) {
+ // Update vi mode cursor hint.
+ if term.mode().contains(TermMode::VI) {
+ let mods = ModifiersState::all();
+ let point = term.vi_mode_cursor.point;
+ self.vi_highlighted_hint = hint::highlighted_at(&term, config, point, mods);
+ } else {
+ self.vi_highlighted_hint = None;
+ }
+
+ // Abort if mouse highlighting conditions are not met.
+ if !mouse.inside_text_area || !term.selection.as_ref().map_or(true, Selection::is_empty) {
+ self.highlighted_hint = None;
+ return;
+ }
+
+ // Find highlighted hint at mouse position.
+ let point = viewport_to_point(term.grid().display_offset(), mouse.point);
+ let highlighted_hint = hint::highlighted_at(&term, config, point, modifiers);
+
+ // Update cursor shape.
+ if highlighted_hint.is_some() {
+ self.window.set_mouse_cursor(CursorIcon::Hand);
+ } else if self.highlighted_hint.is_some() {
+ if term.mode().intersects(TermMode::MOUSE_MODE) && !term.mode().contains(TermMode::VI) {
+ self.window.set_mouse_cursor(CursorIcon::Default);
+ } else {
+ self.window.set_mouse_cursor(CursorIcon::Text);
+ }
+ }
+
+ self.highlighted_hint = highlighted_hint;
+ }
+
/// Format search regex to account for the cursor and fullwidth characters.
fn format_search(size_info: &SizeInfo, search_regex: &str, search_label: &str) -> String {
// Add spacers for wide chars.
@@ -782,6 +808,18 @@ impl Display {
}
}
+/// Convert a terminal point to a viewport relative point.
+pub fn point_to_viewport(display_offset: usize, point: Point) -> Option<Point<usize>> {
+ let viewport_line = point.line.0 + display_offset as i32;
+ usize::try_from(viewport_line).ok().map(|line| Point::new(line, point.column))
+}
+
+/// Convert a viewport relative point to a terminal point.
+pub fn viewport_to_point(display_offset: usize, point: Point<usize>) -> Point {
+ let line = Line(point.line as i32) - display_offset;
+ Point::new(line, point.column)
+}
+
/// Calculate the cell dimensions based on font metrics.
///
/// This will return a tuple of the cell width and height.