oak_php/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
16pub struct PhpHighlighter {
17    pub use_parser: bool,
18}
19
20impl Default for PhpHighlighter {
21    fn default() -> Self {
22        Self { use_parser: false }
23    }
24}
25
26impl PhpHighlighter {
27    pub fn new() -> Self {
28        Self::default()
29    }
30
31    pub fn with_parser() -> Self {
32        Self { use_parser: true }
33    }
34
35    fn highlight_keywords(&self, text: &str) -> Vec<(usize, usize, HighlightKind)> {
36        let mut highlights = Vec::new();
37        let keywords = [
38            "abstract",
39            "and",
40            "array",
41            "as",
42            "break",
43            "callable",
44            "case",
45            "catch",
46            "class",
47            "clone",
48            "const",
49            "continue",
50            "declare",
51            "default",
52            "die",
53            "do",
54            "echo",
55            "else",
56            "elsif",
57            "empty",
58            "enddeclare",
59            "endfor",
60            "endforeach",
61            "endif",
62            "endswitch",
63            "endwhile",
64            "eval",
65            "exit",
66            "extends",
67            "final",
68            "finally",
69            "for",
70            "foreach",
71            "function",
72            "global",
73            "goto",
74            "if",
75            "implements",
76            "include",
77            "include_once",
78            "instanceof",
79            "insteadof",
80            "interface",
81            "isset",
82            "list",
83            "namespace",
84            "new",
85            "or",
86            "print",
87            "private",
88            "protected",
89            "public",
90            "require",
91            "require_once",
92            "return",
93            "static",
94            "switch",
95            "throw",
96            "trait",
97            "try",
98            "unset",
99            "use",
100            "var",
101            "while",
102            "xor",
103            "yield",
104        ];
105
106        for keyword in &keywords {
107            let mut start = 0;
108            while let Some(pos) = text[start..].find(keyword) {
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 PhpHighlighter {
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}