1use ui::{prelude::*, HighlightedLabel};
2
3#[derive(Clone)]
4pub struct HighlightedMatchWithPaths {
5 pub match_label: HighlightedText,
6 pub paths: Vec<HighlightedText>,
7}
8
9#[derive(Debug, Clone, IntoElement)]
10pub struct HighlightedText {
11 pub text: String,
12 pub highlight_positions: Vec<usize>,
13 pub char_count: usize,
14}
15
16impl HighlightedText {
17 pub fn join(components: impl Iterator<Item = Self>, separator: &str) -> Self {
18 let mut char_count = 0;
19 let separator_char_count = separator.chars().count();
20 let mut text = String::new();
21 let mut highlight_positions = Vec::new();
22 for component in components {
23 if char_count != 0 {
24 text.push_str(separator);
25 char_count += separator_char_count;
26 }
27
28 highlight_positions.extend(
29 component
30 .highlight_positions
31 .iter()
32 .map(|position| position + char_count),
33 );
34 text.push_str(&component.text);
35 char_count += component.text.chars().count();
36 }
37
38 Self {
39 text,
40 highlight_positions,
41 char_count,
42 }
43 }
44}
45
46impl RenderOnce for HighlightedText {
47 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
48 HighlightedLabel::new(self.text, self.highlight_positions)
49 }
50}
51
52impl HighlightedMatchWithPaths {
53 pub fn render_paths_children(&mut self, element: Div) -> Div {
54 element.children(self.paths.clone().into_iter().map(|path| {
55 HighlightedLabel::new(path.text, path.highlight_positions)
56 .size(LabelSize::Small)
57 .color(Color::Muted)
58 }))
59 }
60}
61
62impl RenderOnce for HighlightedMatchWithPaths {
63 fn render(mut self, _: &mut WindowContext) -> impl IntoElement {
64 v_flex()
65 .child(self.match_label.clone())
66 .when(!self.paths.is_empty(), |this| {
67 self.render_paths_children(this)
68 })
69 }
70}