oak_pascal/lsp/highlighter/
mod.rs1#![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
11pub trait Highlighter {
13 fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)>;
15}
16
17pub 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}