keyword_highlighter/
keyword_highlighter.rs

1use lineeditor::style::Style;
2use lineeditor::styled_buffer::StyledBuffer;
3use lineeditor::Color;
4use lineeditor::Highlighter;
5use lineeditor::LineEditor;
6use lineeditor::LineEditorResult;
7use lineeditor::StringPrompt;
8
9const GITQL_RESERVED_KEYWORDS: [&str; 31] = [
10    "set", "select", "distinct", "from", "group", "where", "having", "offset", "limit", "order",
11    "by", "case", "when", "then", "else", "end", "between", "in", "is", "not", "like", "glob",
12    "or", "and", "xor", "true", "false", "null", "as", "asc", "desc",
13];
14
15#[derive(Default)]
16pub struct GitQLHighlighter {}
17
18impl Highlighter for GitQLHighlighter {
19    fn highlight(&self, buffer: &mut StyledBuffer) {
20        let lines = buffer.buffer().clone();
21        let mut i: usize = 0;
22
23        let mut keyword_style = Style::default();
24        keyword_style.set_foreground_color(Color::Magenta);
25
26        let mut string_style = Style::default();
27        string_style.set_foreground_color(Color::Yellow);
28
29        loop {
30            if i >= lines.len() {
31                break;
32            }
33
34            // Highlight String literal
35            if lines[i] == '"' {
36                buffer.style_char(i, string_style.clone());
37                i += 1;
38
39                while i < lines.len() && lines[i] != '"' {
40                    buffer.style_char(i, string_style.clone());
41                    i += 1;
42                }
43
44                if i < lines.len() && lines[i] == '"' {
45                    buffer.style_char(i, string_style.clone());
46                    i += 1;
47                }
48
49                continue;
50            }
51
52            // Highlight reserved keyword
53            if lines[i].is_alphabetic() {
54                let start = i;
55                let mut keyword = String::new();
56                while i < lines.len() && (lines[i].is_alphanumeric() || lines[i] == '_') {
57                    keyword.push(lines[i]);
58                    i += 1;
59                }
60
61                keyword = keyword.to_lowercase();
62                if GITQL_RESERVED_KEYWORDS.contains(&keyword.as_str()) {
63                    buffer.style_range(start, i, keyword_style.clone())
64                }
65                continue;
66            }
67
68            i += 1;
69        }
70    }
71}
72
73fn main() {
74    let prompt = StringPrompt::new("prompt> ".to_string());
75    let mut line_editor = LineEditor::new(Box::new(prompt));
76
77    let bindings = line_editor.keybinding();
78    bindings.register_common_control_bindings();
79
80    line_editor.add_highlighter(Box::<GitQLHighlighter>::default());
81
82    match line_editor.read_line() {
83        Ok(LineEditorResult::Success(line)) => {
84            println!("Line {}", line);
85        }
86        _ => {}
87    }
88}