Skip to main content

oak_pascal/highlighter/
mod.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum HighlightKind {
3    Keyword,
4    String,
5    Number,
6    Comment,
7    Identifier,
8}
9
10/// 高亮器 trait
11pub trait Highlighter {
12    /// 对给定的文本进行高亮处理
13    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)>;
14}
15
16/// Pascal 语法高亮器
17pub struct PascalHighlighter {
18    pub use_parser: bool,
19}
20
21impl Default for PascalHighlighter {
22    fn default() -> Self {
23        Self { use_parser: false }
24    }
25}
26
27impl PascalHighlighter {
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    pub fn with_parser() -> Self {
33        Self { use_parser: true }
34    }
35
36    fn highlight_keywords(&self, text: &str) -> Vec<(usize, usize, HighlightKind)> {
37        let mut highlights = Vec::new();
38        let keywords = [
39            "and",
40            "array",
41            "as",
42            "asm",
43            "begin",
44            "case",
45            "class",
46            "const",
47            "constructor",
48            "destructor",
49            "dispinterface",
50            "div",
51            "do",
52            "downto",
53            "else",
54            "end",
55            "except",
56            "exports",
57            "file",
58            "finalization",
59            "finally",
60            "for",
61            "function",
62            "goto",
63            "if",
64            "implementation",
65            "in",
66            "inherited",
67            "initialization",
68            "inline",
69            "interface",
70            "is",
71            "label",
72            "library",
73            "mod",
74            "nil",
75            "not",
76            "object",
77            "of",
78            "or",
79            "out",
80            "packed",
81            "procedure",
82            "program",
83            "property",
84            "raise",
85            "record",
86            "repeat",
87            "resourcestring",
88            "set",
89            "shl",
90            "shr",
91            "string",
92            "then",
93            "threadvar",
94            "to",
95            "try",
96            "type",
97            "unit",
98            "until",
99            "uses",
100            "var",
101            "while",
102            "with",
103            "xor",
104        ];
105
106        for keyword in &keywords {
107            let mut start = 0;
108            while let Some(pos) = text[start..].to_lowercase().find(&keyword.to_lowercase()) {
109                let absolute_pos = start + pos;
110                let end_pos = absolute_pos + keyword.len();
111
112                let is_word_boundary_before = absolute_pos == 0 || !text.chars().nth(absolute_pos - 1).unwrap_or(' ').is_alphanumeric();
113                let is_word_boundary_after = end_pos >= text.len() || !text.chars().nth(end_pos).unwrap_or(' ').is_alphanumeric();
114
115                if is_word_boundary_before && is_word_boundary_after {
116                    highlights.push((absolute_pos, end_pos, HighlightKind::Keyword));
117                }
118
119                start = absolute_pos + 1;
120            }
121        }
122
123        highlights
124    }
125}
126
127impl Highlighter for PascalHighlighter {
128    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)> {
129        let mut highlights = self.highlight_keywords(text);
130        highlights.sort_by_key(|h| h.0);
131        highlights
132    }
133}