1use crate::schema::{ColorRole, Paint};
14use crate::spans::TextSpan;
15
16pub fn role_for_highlight(name: &str) -> Option<ColorRole> {
23 const TABLE: &[(&str, ColorRole)] = &[
25 ("string.escape", ColorRole::SyntaxEscape),
26 ("string.regexp", ColorRole::SyntaxEscape),
27 ("string.regex", ColorRole::SyntaxEscape),
28 ("constant.character.escape", ColorRole::SyntaxEscape),
29 ("function.macro", ColorRole::SyntaxMacro),
30 ("keyword.directive", ColorRole::SyntaxMacro),
31 ("keyword.import", ColorRole::SyntaxKeyword),
32 ("variable.member", ColorRole::SyntaxProperty),
33 ("variable.other.member", ColorRole::SyntaxProperty),
34 ("tag.attribute", ColorRole::SyntaxAttribute),
35 ("constructor", ColorRole::SyntaxFunction),
36 ("keyword", ColorRole::SyntaxKeyword),
37 ("conditional", ColorRole::SyntaxKeyword),
38 ("repeat", ColorRole::SyntaxKeyword),
39 ("exception", ColorRole::SyntaxKeyword),
40 ("include", ColorRole::SyntaxKeyword),
41 ("storageclass", ColorRole::SyntaxKeyword),
42 ("modifier", ColorRole::SyntaxKeyword),
43 ("string", ColorRole::SyntaxString),
44 ("character", ColorRole::SyntaxString),
45 ("comment", ColorRole::SyntaxComment),
46 ("number", ColorRole::SyntaxNumber),
47 ("float", ColorRole::SyntaxNumber),
48 ("boolean", ColorRole::SyntaxConstant),
49 ("constant", ColorRole::SyntaxConstant),
50 ("enumMember", ColorRole::SyntaxConstant),
51 ("type", ColorRole::SyntaxType),
52 ("typeParameter", ColorRole::SyntaxType),
53 ("class", ColorRole::SyntaxType),
54 ("struct", ColorRole::SyntaxType),
55 ("enum", ColorRole::SyntaxType),
56 ("interface", ColorRole::SyntaxType),
57 ("namespace", ColorRole::SyntaxType),
58 ("module", ColorRole::SyntaxType),
59 ("function", ColorRole::SyntaxFunction),
60 ("method", ColorRole::SyntaxFunction),
61 ("variable", ColorRole::SyntaxVariable),
62 ("parameter", ColorRole::SyntaxVariable),
63 ("property", ColorRole::SyntaxProperty),
64 ("field", ColorRole::SyntaxProperty),
65 ("operator", ColorRole::SyntaxOperator),
66 ("punctuation", ColorRole::SyntaxPunctuation),
67 ("tag", ColorRole::SyntaxTag),
68 ("attribute", ColorRole::SyntaxAttribute),
69 ("macro", ColorRole::SyntaxMacro),
70 ("preproc", ColorRole::SyntaxMacro),
71 ("define", ColorRole::SyntaxMacro),
72 ("decorator", ColorRole::SyntaxMacro),
73 ("annotation", ColorRole::SyntaxMacro),
74 ("regexp", ColorRole::SyntaxEscape),
75 ("diff.plus", ColorRole::DiffAdded),
76 ("diff.minus", ColorRole::DiffRemoved),
77 ("diff.delta", ColorRole::DiffModified),
78 ];
79 let matches = |prefix: &str| {
80 name.strip_prefix(prefix)
81 .is_some_and(|rest| rest.is_empty() || rest.starts_with('.'))
82 };
83 TABLE
84 .iter()
85 .filter(|(prefix, _)| matches(prefix))
86 .max_by_key(|(prefix, _)| prefix.len())
87 .map(|(_, role)| *role)
88}
89
90pub fn highlight_span(start: u32, length: u32, name: &str) -> Option<TextSpan> {
93 role_for_highlight(name).map(|role| TextSpan::new(start, length).with_color(Paint::Role(role)))
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
102 fn fr13_1_3_highlight_names_fold_into_the_code_roles() {
103 for (name, role) in [
104 ("keyword", ColorRole::SyntaxKeyword),
105 ("keyword.return", ColorRole::SyntaxKeyword),
106 ("keyword.directive", ColorRole::SyntaxMacro),
107 ("string", ColorRole::SyntaxString),
108 ("string.special", ColorRole::SyntaxString),
109 ("string.escape", ColorRole::SyntaxEscape),
110 ("string.regexp", ColorRole::SyntaxEscape),
111 ("character", ColorRole::SyntaxString),
112 ("comment.documentation", ColorRole::SyntaxComment),
113 ("number", ColorRole::SyntaxNumber),
114 ("float", ColorRole::SyntaxNumber),
115 ("constant.builtin", ColorRole::SyntaxConstant),
116 ("boolean", ColorRole::SyntaxConstant),
117 ("type.builtin", ColorRole::SyntaxType),
118 ("function.method", ColorRole::SyntaxFunction),
119 ("function.macro", ColorRole::SyntaxMacro),
120 ("constructor", ColorRole::SyntaxFunction),
121 ("variable.parameter", ColorRole::SyntaxVariable),
122 ("variable.member", ColorRole::SyntaxProperty),
123 ("property", ColorRole::SyntaxProperty),
124 ("field", ColorRole::SyntaxProperty),
125 ("operator", ColorRole::SyntaxOperator),
126 ("punctuation.bracket", ColorRole::SyntaxPunctuation),
127 ("tag", ColorRole::SyntaxTag),
128 ("attribute", ColorRole::SyntaxAttribute),
129 ("preproc", ColorRole::SyntaxMacro),
130 ("diff.plus", ColorRole::DiffAdded),
131 ("diff.minus", ColorRole::DiffRemoved),
132 ("diff.delta", ColorRole::DiffModified),
133 ] {
134 assert_eq!(role_for_highlight(name), Some(role), "{name}");
135 }
136 }
137
138 #[test]
140 fn fr13_1_3_an_unknown_name_is_left_unpainted() {
141 assert_eq!(role_for_highlight("embedded"), None);
142 assert_eq!(role_for_highlight("spell"), None);
143 assert_eq!(role_for_highlight("keywords"), None);
144 assert!(highlight_span(0, 3, "none").is_none());
145 }
146}