summaryrefslogtreecommitdiff
path: root/src/grid/mod.rs
diff options
context:
space:
mode:
authorChristian Duerr <chrisduerr@users.noreply.github.com>2019-03-30 09:23:48 +0000
committerGitHub <noreply@github.com>2019-03-30 09:23:48 +0000
commit91aa683bcd060b2ac2f621a388a6448f564d0537 (patch)
tree924c9a0759a84be19e397eae8cc28cbd3500d553 /src/grid/mod.rs
parent28636923e02a6cfac0fc950b963623cbcad5fda9 (diff)
downloadalacritty-91aa683bcd060b2ac2f621a388a6448f564d0537.tar.gz
alacritty-91aa683bcd060b2ac2f621a388a6448f564d0537.zip
Rework URL highlighting
This completely reworks URL highlighting to fix two issues which were caused by the original approach. The primary issues that were not straight-forward to resolve with the previous implementation were about handling the URL highlighted content moving while the highlight is active. This lead to issues with highlighting with scrolling and when the display offset was not 0. The new approach sticks closely to prior art done for the selection, where the selection is tracked on the grid and updated whenever the buffer is rotated. The truncation of URLs was incorrectly assuming input to be just a single codepoint wide to truncate the end of URLs with unmatching closing parenthesis. This is now handled properly using Rust's built-in Unicode support. This fixes #2231. This fixes #2225.
Diffstat (limited to 'src/grid/mod.rs')
-rw-r--r--src/grid/mod.rs57
1 files changed, 45 insertions, 12 deletions
diff --git a/src/grid/mod.rs b/src/grid/mod.rs
index 272ea340..a1903535 100644
--- a/src/grid/mod.rs
+++ b/src/grid/mod.rs
@@ -15,9 +15,9 @@
//! A specialized 2d grid implementation optimized for use in a terminal.
use std::cmp::{min, max, Ordering};
-use std::ops::{Deref, Range, Index, IndexMut, RangeTo, RangeFrom, RangeFull};
+use std::ops::{Deref, Range, Index, IndexMut, RangeTo, RangeFrom, RangeFull, RangeInclusive};
-use crate::index::{self, Point, Line, Column, IndexRange, PointIterator};
+use crate::index::{self, Point, Line, Column, IndexRange};
use crate::selection::Selection;
mod row;
@@ -60,7 +60,8 @@ impl<T: PartialEq> ::std::cmp::PartialEq for Grid<T> {
self.lines.eq(&other.lines) &&
self.display_offset.eq(&other.display_offset) &&
self.scroll_limit.eq(&other.scroll_limit) &&
- self.selection.eq(&other.selection)
+ self.selection.eq(&other.selection) &&
+ self.url_highlight.eq(&other.url_highlight)
}
}
@@ -103,6 +104,10 @@ pub struct Grid<T> {
#[serde(default)]
max_scroll_limit: usize,
+
+ /// Range for URL hover highlights
+ #[serde(default)]
+ pub url_highlight: Option<RangeInclusive<index::Linear>>,
}
#[derive(Copy, Clone)]
@@ -132,6 +137,7 @@ impl<T: GridCell + Copy + Clone> Grid<T> {
scroll_limit: 0,
selection: None,
max_scroll_limit: scrollback,
+ url_highlight: None,
}
}
@@ -387,6 +393,7 @@ impl<T: GridCell + Copy + Clone> Grid<T> {
let prev = self.lines;
self.selection = None;
+ self.url_highlight = None;
self.raw.rotate(*prev as isize - *target as isize);
self.raw.shrink_visible_lines(target);
self.lines = target;
@@ -422,6 +429,7 @@ impl<T: GridCell + Copy + Clone> Grid<T> {
if let Some(ref mut selection) = self.selection {
selection.rotate(-(*positions as isize));
}
+ self.url_highlight = None;
self.decrease_scroll_limit(*positions);
@@ -473,6 +481,7 @@ impl<T: GridCell + Copy + Clone> Grid<T> {
if let Some(ref mut selection) = self.selection {
selection.rotate(*positions as isize);
}
+ self.url_highlight = None;
// // This next loop swaps "fixed" lines outside of a scroll region
// // back into place after the rotation. The work is done in buffer-
@@ -517,6 +526,7 @@ impl<T: GridCell + Copy + Clone> Grid<T> {
self.display_offset = 0;
self.selection = None;
+ self.url_highlight = None;
}
}
@@ -573,7 +583,7 @@ impl<T> Grid<T> {
pub fn iter_from(&self, point: Point<usize>) -> GridIterator<'_, T> {
GridIterator {
grid: self,
- point_iter: point.iter(self.num_cols() - 1, self.len() - 1),
+ cur: point,
}
}
@@ -589,27 +599,50 @@ impl<T> Grid<T> {
}
pub struct GridIterator<'a, T> {
- point_iter: PointIterator<usize>,
+ /// Immutable grid reference
grid: &'a Grid<T>,
-}
-impl<'a, T> GridIterator<'a, T> {
- pub fn cur(&self) -> Point<usize> {
- self.point_iter.cur
- }
+ /// Current position of the iterator within the grid.
+ pub cur: Point<usize>,
}
impl<'a, T> Iterator for GridIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
- self.point_iter.next().map(|p| &self.grid[p.line][p.col])
+ let last_col = self.grid.num_cols() - Column(1);
+ match self.cur {
+ Point { line, col } if line == 0 && col == last_col => None,
+ Point { col, .. } if
+ (col == last_col) => {
+ self.cur.line -= 1;
+ self.cur.col = Column(0);
+ Some(&self.grid[self.cur.line][self.cur.col])
+ },
+ _ => {
+ self.cur.col += Column(1);
+ Some(&self.grid[self.cur.line][self.cur.col])
+ }
+ }
}
}
impl<'a, T> BidirectionalIterator for GridIterator<'a, T> {
fn prev(&mut self) -> Option<Self::Item> {
- self.point_iter.prev().map(|p| &self.grid[p.line][p.col])
+ let num_cols = self.grid.num_cols();
+
+ match self.cur {
+ Point { line, col: Column(0) } if line == self.grid.len() - 1 => None,
+ Point { col: Column(0), .. } => {
+ self.cur.line += 1;
+ self.cur.col = num_cols - Column(1);
+ Some(&self.grid[self.cur.line][self.cur.col])
+ },
+ _ => {
+ self.cur.col -= Column(1);
+ Some(&self.grid[self.cur.line][self.cur.col])
+ }
+ }
}
}