1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum HighlightKind {
3 Keyword,
4 String,
5 Number,
6 Comment,
7 Identifier,
8}
9
10pub trait Highlighter {
12 fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)>;
14}
15
16pub 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}