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