search.rs

 1use std::{borrow::Cow, ops::Deref};
 2
 3use alacritty_terminal::{
 4    grid::Dimensions,
 5    index::{Column, Direction, Line, Point},
 6    term::search::{Match, RegexIter, RegexSearch},
 7    Term,
 8};
 9
10const MAX_SEARCH_LINES: usize = 100;
11
12///Header and impl fom alacritty/src/display/content.rs HintMatches
13#[derive(Default)]
14pub struct SearchMatches<'a> {
15    /// All visible matches.
16    matches: Cow<'a, [Match]>,
17
18    /// Index of the last match checked.
19    index: usize,
20}
21
22impl<'a> SearchMatches<'a> {
23    /// Create new renderable matches iterator..
24    fn new(matches: impl Into<Cow<'a, [Match]>>) -> Self {
25        Self {
26            matches: matches.into(),
27            index: 0,
28        }
29    }
30
31    /// Create from regex matches on term visable part.
32    pub fn visible_regex_matches<T>(term: &Term<T>, dfas: &RegexSearch) -> Self {
33        let matches = visible_regex_match_iter(term, dfas).collect::<Vec<_>>();
34        Self::new(matches)
35    }
36
37    /// Advance the regex tracker to the next point.
38    ///
39    /// This will return `true` if the point passed is part of a regex match.
40    fn advance(&mut self, point: Point) -> bool {
41        while let Some(bounds) = self.get(self.index) {
42            if bounds.start() > &point {
43                break;
44            } else if bounds.end() < &point {
45                self.index += 1;
46            } else {
47                return true;
48            }
49        }
50        false
51    }
52}
53
54impl<'a> Deref for SearchMatches<'a> {
55    type Target = [Match];
56
57    fn deref(&self) -> &Self::Target {
58        self.matches.deref()
59    }
60}
61
62/// Copied from alacritty/src/display/hint.rs
63/// Iterate over all visible regex matches.
64fn visible_regex_match_iter<'a, T>(
65    term: &'a Term<T>,
66    regex: &'a RegexSearch,
67) -> impl Iterator<Item = Match> + 'a {
68    let viewport_start = Line(-(term.grid().display_offset() as i32));
69    let viewport_end = viewport_start + term.bottommost_line();
70    let mut start = term.line_search_left(Point::new(viewport_start, Column(0)));
71    let mut end = term.line_search_right(Point::new(viewport_end, Column(0)));
72    start.line = start.line.max(viewport_start - MAX_SEARCH_LINES);
73    end.line = end.line.min(viewport_end + MAX_SEARCH_LINES);
74
75    RegexIter::new(start, end, Direction::Right, term, regex)
76        .skip_while(move |rm| rm.end().line < viewport_start)
77        .take_while(move |rm| rm.start().line <= viewport_end)
78}