Apply post processing to hyperlink. So less regexs with unlikely trailing characters are matches
This commit is contained in:
parent
ff42dd2a97
commit
75e1082260
1 changed files with 162 additions and 3 deletions
165
src/terminal.rs
165
src/terminal.rs
|
|
@ -701,9 +701,15 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
term.reset_damage();
|
term.reset_damage();
|
||||||
|
|
||||||
let regex_match_iter = visible_regex_match_iter(&term, &mut self.url_regex_search);
|
|
||||||
self.regex_matches.clear();
|
self.regex_matches.clear();
|
||||||
self.regex_matches.extend(regex_match_iter);
|
{
|
||||||
|
let mut regex_matches: Vec<_> =
|
||||||
|
visible_regex_match_iter(&term, &mut self.url_regex_search).collect();
|
||||||
|
self.regex_matches
|
||||||
|
.extend(regex_matches.drain(..).flat_map(|rm| -> Vec<_> {
|
||||||
|
HintPostProcessor::new(&term, &mut self.url_regex_search, rm).collect()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
let grid = term.grid();
|
let grid = term.grid();
|
||||||
for indexed in grid.display_iter() {
|
for indexed in grid.display_iter() {
|
||||||
|
|
@ -962,7 +968,6 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all visible regex matches.
|
/// Iterate over all visible regex matches.
|
||||||
/// This includes the screen +- 100 lines (MAX_SEARCH_LINES).
|
/// This includes the screen +- 100 lines (MAX_SEARCH_LINES).
|
||||||
/// display/hint.rs
|
/// display/hint.rs
|
||||||
|
|
@ -981,6 +986,160 @@ pub fn visible_regex_match_iter<'a, T>(
|
||||||
.skip_while(move |rm| rm.end().line < viewport_start)
|
.skip_while(move |rm| rm.end().line < viewport_start)
|
||||||
.take_while(move |rm| rm.start().line <= viewport_end)
|
.take_while(move |rm| rm.start().line <= viewport_end)
|
||||||
}
|
}
|
||||||
|
/** Copy of <https://github.com/alacritty/alacritty/blob/4a7728bf7fac06a35f27f6c4f31e0d9214e5152b/alacritty/src/display/hint.rs#L433C1-L572C1> */
|
||||||
|
/// Iterator over all post-processed matches inside an existing hint match.
|
||||||
|
struct HintPostProcessor<'a, T> {
|
||||||
|
/// Regex search DFAs.
|
||||||
|
regex: &'a mut RegexSearch,
|
||||||
|
|
||||||
|
/// Terminal reference.
|
||||||
|
term: &'a Term<T>,
|
||||||
|
|
||||||
|
/// Next hint match in the iterator.
|
||||||
|
next_match: Option<alacritty_terminal::term::search::Match>,
|
||||||
|
|
||||||
|
/// Start point for the next search.
|
||||||
|
start: Point,
|
||||||
|
|
||||||
|
/// End point for the hint match iterator.
|
||||||
|
end: Point,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> HintPostProcessor<'a, T> {
|
||||||
|
/// Create a new iterator for an unprocessed match.
|
||||||
|
fn new(
|
||||||
|
term: &'a Term<T>,
|
||||||
|
regex: &'a mut RegexSearch,
|
||||||
|
regex_match: alacritty_terminal::term::search::Match,
|
||||||
|
) -> Self {
|
||||||
|
let mut post_processor = Self {
|
||||||
|
next_match: None,
|
||||||
|
start: *regex_match.start(),
|
||||||
|
end: *regex_match.end(),
|
||||||
|
term,
|
||||||
|
regex,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Post-process the first hint match.
|
||||||
|
post_processor.next_processed_match(regex_match);
|
||||||
|
|
||||||
|
post_processor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply some hint post processing heuristics.
|
||||||
|
///
|
||||||
|
/// This will check the end of the hint and make it shorter if certain characters are determined
|
||||||
|
/// to be unlikely to be intentionally part of the hint.
|
||||||
|
///
|
||||||
|
/// This is most useful for identifying URLs appropriately.
|
||||||
|
fn hint_post_processing(
|
||||||
|
&self,
|
||||||
|
regex_match: &alacritty_terminal::term::search::Match,
|
||||||
|
) -> Option<alacritty_terminal::term::search::Match> {
|
||||||
|
let mut iter = self.term.grid().iter_from(*regex_match.start());
|
||||||
|
|
||||||
|
let mut c = iter.cell().c;
|
||||||
|
|
||||||
|
// Truncate uneven number of brackets.
|
||||||
|
let end = *regex_match.end();
|
||||||
|
let mut open_parents = 0;
|
||||||
|
let mut open_brackets = 0;
|
||||||
|
loop {
|
||||||
|
match c {
|
||||||
|
'(' => open_parents += 1,
|
||||||
|
'[' => open_brackets += 1,
|
||||||
|
')' => {
|
||||||
|
if open_parents == 0 {
|
||||||
|
alacritty_terminal::grid::BidirectionalIterator::prev(&mut iter);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
open_parents -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
']' => {
|
||||||
|
if open_brackets == 0 {
|
||||||
|
alacritty_terminal::grid::BidirectionalIterator::prev(&mut iter);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
open_brackets -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
if iter.point() == end {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
match iter.next() {
|
||||||
|
Some(indexed) => c = indexed.cell.c,
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate trailing characters which are likely to be delimiters.
|
||||||
|
let start = *regex_match.start();
|
||||||
|
while iter.point() != start {
|
||||||
|
if !matches!(c, '.' | ',' | ':' | ';' | '?' | '!' | '(' | '[' | '\'') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
match alacritty_terminal::grid::BidirectionalIterator::prev(&mut iter) {
|
||||||
|
Some(indexed) => c = indexed.cell.c,
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if start > iter.point() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(start..=iter.point())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loop over submatches until a non-empty post-processed match is found.
|
||||||
|
fn next_processed_match(&mut self, mut regex_match: alacritty_terminal::term::search::Match) {
|
||||||
|
self.next_match = loop {
|
||||||
|
if let Some(next_match) = self.hint_post_processing(®ex_match) {
|
||||||
|
self.start = next_match.end().add(self.term, Boundary::Grid, 1);
|
||||||
|
break Some(next_match);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.start = regex_match.start().add(self.term, Boundary::Grid, 1);
|
||||||
|
if self.start > self.end {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self
|
||||||
|
.term
|
||||||
|
.regex_search_right(self.regex, self.start, self.end)
|
||||||
|
{
|
||||||
|
Some(rm) => regex_match = rm,
|
||||||
|
None => return,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Iterator for HintPostProcessor<'a, T> {
|
||||||
|
type Item = alacritty_terminal::term::search::Match;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let next_match = self.next_match.take()?;
|
||||||
|
|
||||||
|
if self.start <= self.end {
|
||||||
|
if let Some(rm) = self
|
||||||
|
.term
|
||||||
|
.regex_search_right(self.regex, self.start, self.end)
|
||||||
|
{
|
||||||
|
self.next_processed_match(rm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(next_match)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for Terminal {
|
impl Drop for Terminal {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Ensure shutdown on terminal drop
|
// Ensure shutdown on terminal drop
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue