Repository: alacritty/alacritty
File: alacritty/src/display/hint.rs (Rust)

Code before:

            match iter.prev() {
                Some(indexed) => c = indexed.cell.c,
                None => break,
            }
        }

        if start > iter.point() {
            None
        } else {
            Some(start..=iter.point())
        }
    }

    /// Loops over processed matches until a match is found or the
    /// range is exhausted.
    fn iterate_to_next_processed_match(&mut self, mut regex_match: Match) {
        self.next_match = None;

        while regex_match.start() <= regex_match.end() {
            self.next_match = self.hint_post_processing(&regex_match);

            regex_match = match self.next_match {
                Some(_) => break,
                None => regex_match.start().add(self.term, Boundary::Grid, 1)..=*regex_match.end(),
            }
        }

        self.start = self
            .next_match
            .as_ref()
            .map_or(*regex_match.start(), |nm| nm.end().add(self.term, Boundary::Grid, 1));
    }
}

impl<'a, T> Iterator for HintPostProcessor<'a, T> {
    type Item = 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.iterate_to_next_processed_match(rm);
            }
        }

        Some(next_match)
    }
}


Review comment (suggestion):
I'm not sure if this contradicts something I've said previously, but I don't think overlapping hint matches should be post-processed multiple times. The `regex_search_right` method is already responsible for handling potential overlaps.

So really if `hint_post_processing` doesn't return a match, the next match must be determined by regex search not by post processing.

Code after:

            match iter.prev() {
                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: Match) {
        self.next_match = loop {
            if let Some(next_match) = self.hint_post_processing(&regex_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 = 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)
    }
}