diff options
Diffstat (limited to 'alacritty/src/display/hint.rs')
-rw-r--r-- | alacritty/src/display/hint.rs | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index a01a1d03..3f10b4e5 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -1,6 +1,8 @@ +use std::borrow::Cow; use std::cmp::Reverse; use std::collections::HashSet; use std::iter; +use std::rc::Rc; use ahash::RandomState; use winit::keyboard::ModifiersState; @@ -23,7 +25,7 @@ const HINT_SPLIT_PERCENTAGE: f32 = 0.5; /// Keyboard regex hint state. pub struct HintState { /// Hint currently in use. - hint: Option<Hint>, + hint: Option<Rc<Hint>>, /// Alphabet for hint labels. alphabet: String, @@ -56,7 +58,7 @@ impl HintState { } /// Start the hint selection process. - pub fn start(&mut self, hint: Hint) { + pub fn start(&mut self, hint: Rc<Hint>) { self.hint = Some(hint); } @@ -150,7 +152,7 @@ impl HintState { // Check if the selected label is fully matched. if label.len() == 1 { let bounds = self.matches[index].clone(); - let action = hint.action.clone(); + let hint = hint.clone(); // Exit hint mode unless it requires explicit dismissal. if hint.persist { @@ -161,7 +163,7 @@ impl HintState { // Hyperlinks take precedence over regex matches. let hyperlink = term.grid()[*bounds.start()].hyperlink(); - Some(HintMatch { action, bounds, hyperlink }) + Some(HintMatch { bounds, hyperlink, hint }) } else { // Store character to preserve the selection. self.keys.push(c); @@ -192,13 +194,14 @@ impl HintState { /// Hint match which was selected by the user. #[derive(PartialEq, Eq, Debug, Clone)] pub struct HintMatch { - /// Action for handling the text. - action: HintAction, - /// Terminal range matching the hint. bounds: Match, + /// OSC 8 hyperlink. hyperlink: Option<Hyperlink>, + + /// Hint which triggered this match. + hint: Rc<Hint>, } impl HintMatch { @@ -210,7 +213,7 @@ impl HintMatch { #[inline] pub fn action(&self) -> &HintAction { - &self.action + &self.hint.action } #[inline] @@ -221,6 +224,29 @@ impl HintMatch { pub fn hyperlink(&self) -> Option<&Hyperlink> { self.hyperlink.as_ref() } + + /// Get the text content of the hint match. + /// + /// This will always revalidate the hint text, to account for terminal content + /// changes since the [`HintMatch`] was constructed. The text of the hint might + /// be different from its original value, but it will **always** be a valid + /// match for this hint. + pub fn text<T>(&self, term: &Term<T>) -> Option<Cow<'_, str>> { + // Revalidate hyperlink match. + if let Some(hyperlink) = &self.hyperlink { + let (validated, bounds) = hyperlink_at(term, *self.bounds.start())?; + return (&validated == hyperlink && bounds == self.bounds) + .then(|| hyperlink.uri().into()); + } + + // Revalidate regex match. + let regex = self.hint.content.regex.as_ref()?; + let bounds = regex.with_compiled(|regex| { + regex_match_at(term, *self.bounds.start(), regex, self.hint.post_processing) + })??; + (bounds == self.bounds) + .then(|| term.bounds_to_string(*bounds.start(), *bounds.end()).into()) + } } /// Generator for creating new hint labels. @@ -382,18 +408,14 @@ pub fn highlighted_at<T>( if let Some((hyperlink, bounds)) = hint.content.hyperlinks.then(|| hyperlink_at(term, point)).flatten() { - return Some(HintMatch { - bounds, - action: hint.action.clone(), - hyperlink: Some(hyperlink), - }); + return Some(HintMatch { bounds, hyperlink: Some(hyperlink), hint: hint.clone() }); } let bounds = hint.content.regex.as_ref().and_then(|regex| { regex.with_compiled(|regex| regex_match_at(term, point, regex, hint.post_processing)) }); if let Some(bounds) = bounds.flatten() { - return Some(HintMatch { bounds, action: hint.action.clone(), hyperlink: None }); + return Some(HintMatch { bounds, hint: hint.clone(), hyperlink: None }); } None @@ -554,7 +576,7 @@ impl<'a, T> HintPostProcessor<'a, T> { } } -impl<'a, T> Iterator for HintPostProcessor<'a, T> { +impl<T> Iterator for HintPostProcessor<'_, T> { type Item = Match; fn next(&mut self) -> Option<Self::Item> { |