@@ -417,7 +417,18 @@ fn parse_ansi(s: &str) -> Vec<(usize, usize, usize)> {
417417///
418418/// * `match_indices` - Indices of graphemes (NOT bytes or chars) that matched the typed text
419419/// * `match_style` - Style to use for matched characters
420- pub fn style_suggestion(suggestion: &str, match_indices: &[usize], match_style: &Style) -> String {
420+ pub fn style_suggestion(
421+ suggestion: &str,
422+ match_indices: &[usize],
423+ text_style: &Style,
424+ match_style: &Style,
425+ selected_style: Option<&Style>,
426+ ) -> String {
427+ let text_style_prefix = text_style.prefix().to_string();
428+ let match_style_prefix = match_style.prefix().to_string();
429+ let selected_prefix = selected_style
430+ .map(|s| s.prefix().to_string())
431+ .unwrap_or_default();
421432 let mut res = String::new();
422433 let mut offset = 0;
423434 for (escape_start, text_start, text_end) in parse_ansi(suggestion) {
@@ -426,14 +437,18 @@ pub fn style_suggestion(suggestion: &str, match_indices: &[usize], match_style:
426437 let graphemes = text.graphemes(true).collect::<Vec<_>>();
427438 let mut prev_matched = false;
428439
440+ res.push_str(&text_style_prefix);
441+ res.push_str(&selected_prefix);
429442 res.push_str(escape);
430443 for (i, grapheme) in graphemes.iter().enumerate() {
431444 let is_match = match_indices.contains(&(i + offset));
432445
433446 if is_match && !prev_matched {
434- res.push_str(&match_style.prefix().to_string() );
447+ res.push_str(&match_style_prefix );
435448 } else if !is_match && prev_matched && i != 0 {
436449 res.push_str(RESET);
450+ res.push_str(&text_style_prefix);
451+ res.push_str(&selected_prefix);
437452 res.push_str(escape);
438453 }
439454 res.push_str(grapheme);
@@ -826,22 +841,38 @@ mod tests {
826841
827842 #[test]
828843 fn style_fuzzy_suggestion() {
844+ let text_style = Style::new().fg(Color::Red);
829845 let match_style = Style::new().underline();
846+ let selected_style = Style::new().underline();
830847 let style1 = Style::new().on(Color::Blue);
831848 let style2 = Style::new().on(Color::Green);
832849
833850 let expected = format!(
834- "{}{}{}{}{}{}{}{}{}{}{}{}{}",
851+ "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
852+ text_style.prefix(),
853+ selected_style.prefix(),
835854 style1.prefix(),
836855 "ab",
837856 match_style.paint("汉"),
857+ text_style.prefix(),
858+ selected_style.prefix(),
838859 style1.prefix(),
839860 "d",
861+ // TODO these next two are unnecessary, make sure consecutive ANSI escapes
862+ // are treated as a single segment by parse_ansi()
863+ text_style.prefix(),
864+ selected_style.prefix(),
840865 RESET,
866+ text_style.prefix(),
867+ selected_style.prefix(),
841868 style2.prefix(),
842869 match_style.paint("y̆👩🏾"),
870+ text_style.prefix(),
871+ selected_style.prefix(),
843872 style2.prefix(),
844873 "e",
874+ text_style.prefix(),
875+ selected_style.prefix(),
845876 RESET,
846877 "b@",
847878 match_style.paint("r"),
@@ -856,7 +887,9 @@ mod tests {
856887 style_suggestion(
857888 &format!("{}{}{}", style1.paint("ab汉d"), style2.paint("y̆👩🏾e"), "b@r"),
858889 match_indices,
859- &match_style
890+ &text_style,
891+ &match_style,
892+ Some(&selected_style),
860893 )
861894 );
862895 }
@@ -866,20 +899,10 @@ mod tests {
866899 let text_style = Style::new().on(Color::Blue).bold();
867900 let match_style = Style::new().underline();
868901
869- let expected = format!(
870- "{}{}{}{}",
871- text_style.prefix(),
872- "go",
873- match_style.paint("o"),
874- RESET
875- );
902+ let expected = format!("{}{}{}", text_style.prefix(), "go", match_style.paint("o"),);
876903 assert_eq!(
877904 expected,
878- style_suggestion(
879- &text_style.paint("goo").to_string(),
880- &[2, 3, 4, 6],
881- &match_style
882- )
905+ style_suggestion("goo", &[2, 3, 4, 6], &text_style, &match_style, None)
883906 );
884907 }
885908
0 commit comments