Skip to main content

raps_cli/shell/
highlighter.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2025 Dmytro Yemelianov
3
4use std::collections::HashSet;
5
6use reedline::{Highlighter, StyledText};
7// StyledText uses nu_ansi_term's Style/Color for syntax highlighting.
8use nu_ansi_term::{Color as AnsiColor, Style};
9
10use super::command_tree::build_command_tree;
11
12/// Colors recognized commands green in the input line.
13pub struct RapsHighlighter {
14    command_names: HashSet<&'static str>,
15}
16
17impl RapsHighlighter {
18    pub fn new() -> Self {
19        let commands = build_command_tree();
20        let command_names = commands.iter().map(|c| c.name).collect();
21        Self { command_names }
22    }
23}
24
25impl Default for RapsHighlighter {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl Highlighter for RapsHighlighter {
32    fn highlight(&self, line: &str, _cursor: usize) -> StyledText {
33        let mut styled = StyledText::new();
34
35        if line.is_empty() {
36            return styled;
37        }
38
39        let first_word_end = line.find(' ').unwrap_or(line.len());
40        let cmd = &line[..first_word_end];
41
42        if self.command_names.contains(cmd) {
43            styled.push((Style::new().fg(AnsiColor::Green), cmd.to_string()));
44        } else {
45            styled.push((Style::default(), cmd.to_string()));
46        }
47
48        if first_word_end < line.len() {
49            styled.push((Style::default(), line[first_word_end..].to_string()));
50        }
51
52        styled
53    }
54}