use crate::schema::{ColorRole, Paint};
use crate::spans::TextSpan;
pub fn role_for_highlight(name: &str) -> Option<ColorRole> {
const TABLE: &[(&str, ColorRole)] = &[
("string.escape", ColorRole::SyntaxEscape),
("string.regexp", ColorRole::SyntaxEscape),
("string.regex", ColorRole::SyntaxEscape),
("constant.character.escape", ColorRole::SyntaxEscape),
("function.macro", ColorRole::SyntaxMacro),
("keyword.directive", ColorRole::SyntaxMacro),
("keyword.import", ColorRole::SyntaxKeyword),
("variable.member", ColorRole::SyntaxProperty),
("variable.other.member", ColorRole::SyntaxProperty),
("tag.attribute", ColorRole::SyntaxAttribute),
("constructor", ColorRole::SyntaxFunction),
("keyword", ColorRole::SyntaxKeyword),
("conditional", ColorRole::SyntaxKeyword),
("repeat", ColorRole::SyntaxKeyword),
("exception", ColorRole::SyntaxKeyword),
("include", ColorRole::SyntaxKeyword),
("storageclass", ColorRole::SyntaxKeyword),
("modifier", ColorRole::SyntaxKeyword),
("string", ColorRole::SyntaxString),
("character", ColorRole::SyntaxString),
("comment", ColorRole::SyntaxComment),
("number", ColorRole::SyntaxNumber),
("float", ColorRole::SyntaxNumber),
("boolean", ColorRole::SyntaxConstant),
("constant", ColorRole::SyntaxConstant),
("enumMember", ColorRole::SyntaxConstant),
("type", ColorRole::SyntaxType),
("typeParameter", ColorRole::SyntaxType),
("class", ColorRole::SyntaxType),
("struct", ColorRole::SyntaxType),
("enum", ColorRole::SyntaxType),
("interface", ColorRole::SyntaxType),
("namespace", ColorRole::SyntaxType),
("module", ColorRole::SyntaxType),
("function", ColorRole::SyntaxFunction),
("method", ColorRole::SyntaxFunction),
("variable", ColorRole::SyntaxVariable),
("parameter", ColorRole::SyntaxVariable),
("property", ColorRole::SyntaxProperty),
("field", ColorRole::SyntaxProperty),
("operator", ColorRole::SyntaxOperator),
("punctuation", ColorRole::SyntaxPunctuation),
("tag", ColorRole::SyntaxTag),
("attribute", ColorRole::SyntaxAttribute),
("macro", ColorRole::SyntaxMacro),
("preproc", ColorRole::SyntaxMacro),
("define", ColorRole::SyntaxMacro),
("decorator", ColorRole::SyntaxMacro),
("annotation", ColorRole::SyntaxMacro),
("regexp", ColorRole::SyntaxEscape),
("diff.plus", ColorRole::DiffAdded),
("diff.minus", ColorRole::DiffRemoved),
("diff.delta", ColorRole::DiffModified),
];
let matches = |prefix: &str| {
name.strip_prefix(prefix)
.is_some_and(|rest| rest.is_empty() || rest.starts_with('.'))
};
TABLE
.iter()
.filter(|(prefix, _)| matches(prefix))
.max_by_key(|(prefix, _)| prefix.len())
.map(|(_, role)| *role)
}
pub fn highlight_span(start: u32, length: u32, name: &str) -> Option<TextSpan> {
role_for_highlight(name).map(|role| TextSpan::new(start, length).with_color(Paint::Role(role)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fr13_1_3_highlight_names_fold_into_the_code_roles() {
for (name, role) in [
("keyword", ColorRole::SyntaxKeyword),
("keyword.return", ColorRole::SyntaxKeyword),
("keyword.directive", ColorRole::SyntaxMacro),
("string", ColorRole::SyntaxString),
("string.special", ColorRole::SyntaxString),
("string.escape", ColorRole::SyntaxEscape),
("string.regexp", ColorRole::SyntaxEscape),
("character", ColorRole::SyntaxString),
("comment.documentation", ColorRole::SyntaxComment),
("number", ColorRole::SyntaxNumber),
("float", ColorRole::SyntaxNumber),
("constant.builtin", ColorRole::SyntaxConstant),
("boolean", ColorRole::SyntaxConstant),
("type.builtin", ColorRole::SyntaxType),
("function.method", ColorRole::SyntaxFunction),
("function.macro", ColorRole::SyntaxMacro),
("constructor", ColorRole::SyntaxFunction),
("variable.parameter", ColorRole::SyntaxVariable),
("variable.member", ColorRole::SyntaxProperty),
("property", ColorRole::SyntaxProperty),
("field", ColorRole::SyntaxProperty),
("operator", ColorRole::SyntaxOperator),
("punctuation.bracket", ColorRole::SyntaxPunctuation),
("tag", ColorRole::SyntaxTag),
("attribute", ColorRole::SyntaxAttribute),
("preproc", ColorRole::SyntaxMacro),
("diff.plus", ColorRole::DiffAdded),
("diff.minus", ColorRole::DiffRemoved),
("diff.delta", ColorRole::DiffModified),
] {
assert_eq!(role_for_highlight(name), Some(role), "{name}");
}
}
#[test]
fn fr13_1_3_an_unknown_name_is_left_unpainted() {
assert_eq!(role_for_highlight("embedded"), None);
assert_eq!(role_for_highlight("spell"), None);
assert_eq!(role_for_highlight("keywords"), None);
assert!(highlight_span(0, 3, "none").is_none());
}
}