Skip to main content

oak_pascal/lsp/highlighter/
mod.rs

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