Skip to main content

rgx/ui/
match_display.rs

1use ratatui::{
2    buffer::Buffer,
3    layout::Rect,
4    style::Style,
5    text::{Line, Span},
6    widgets::{Block, Borders, Paragraph, Widget, Wrap},
7};
8
9use crate::engine;
10use crate::ui::theme;
11
12pub struct MatchDisplay<'a> {
13    pub matches: &'a [engine::Match],
14}
15
16impl<'a> Widget for MatchDisplay<'a> {
17    fn render(self, area: Rect, buf: &mut Buffer) {
18        let title = format!(" Matches ({}) ", self.matches.len());
19        let block = Block::default()
20            .borders(Borders::ALL)
21            .border_style(Style::default().fg(theme::OVERLAY))
22            .title(Span::styled(title, Style::default().fg(theme::TEXT)));
23
24        if self.matches.is_empty() {
25            let paragraph = Paragraph::new(Line::from(Span::styled(
26                "No matches",
27                Style::default().fg(theme::SUBTEXT),
28            )))
29            .block(block)
30            .style(Style::default().bg(theme::BASE));
31            paragraph.render(area, buf);
32            return;
33        }
34
35        let mut lines = Vec::new();
36        for (i, m) in self.matches.iter().enumerate() {
37            lines.push(Line::from(vec![
38                Span::styled(
39                    format!("Match {} ", i + 1),
40                    Style::default().fg(theme::BLUE),
41                ),
42                Span::styled(
43                    format!("[{}-{}]: ", m.start, m.end),
44                    Style::default().fg(theme::SUBTEXT),
45                ),
46                Span::styled(
47                    format!("\"{}\"", &m.text),
48                    Style::default().fg(theme::GREEN),
49                ),
50            ]));
51
52            for cap in &m.captures {
53                let color = theme::capture_color(cap.index.saturating_sub(1));
54                let name_str = cap
55                    .name
56                    .as_ref()
57                    .map(|n| format!(" '{n}'"))
58                    .unwrap_or_default();
59                lines.push(Line::from(vec![
60                    Span::styled("  ", Style::default()),
61                    Span::styled(
62                        format!("Group #{}{name_str} ", cap.index),
63                        Style::default().fg(color),
64                    ),
65                    Span::styled(
66                        format!("[{}-{}]: ", cap.start, cap.end),
67                        Style::default().fg(theme::SUBTEXT),
68                    ),
69                    Span::styled(format!("\"{}\"", &cap.text), Style::default().fg(color)),
70                ]));
71            }
72        }
73
74        let paragraph = Paragraph::new(lines)
75            .block(block)
76            .style(Style::default().bg(theme::BASE))
77            .wrap(Wrap { trim: false });
78
79        paragraph.render(area, buf);
80    }
81}