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