use std::{fmt, ops::Range, sync::Arc};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct HighlightCategory(Arc<str>);
impl HighlightCategory {
#[must_use]
pub fn new(s: impl Into<Arc<str>>) -> Self {
Self(s.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for HighlightCategory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl HighlightCategory {
pub const KEYWORD: &str = "keyword";
pub const KEYWORD_CONTROL: &str = "keyword.control";
pub const KEYWORD_OPERATOR: &str = "keyword.operator";
pub const KEYWORD_FUNCTION: &str = "keyword.function";
pub const KEYWORD_TYPE: &str = "keyword.type";
pub const TYPE: &str = "type";
pub const TYPE_BUILTIN: &str = "type.builtin";
pub const FUNCTION: &str = "function";
pub const FUNCTION_BUILTIN: &str = "function.builtin";
pub const FUNCTION_MACRO: &str = "function.macro";
pub const FUNCTION_METHOD: &str = "function.method";
pub const VARIABLE: &str = "variable";
pub const VARIABLE_BUILTIN: &str = "variable.builtin";
pub const VARIABLE_PARAMETER: &str = "variable.parameter";
pub const VARIABLE_FIELD: &str = "variable.field";
pub const CONSTANT: &str = "constant";
pub const STRING: &str = "string";
pub const STRING_ESCAPE: &str = "string.escape";
pub const CHARACTER: &str = "character";
pub const NUMBER: &str = "number";
pub const BOOLEAN: &str = "boolean";
pub const COMMENT: &str = "comment";
pub const COMMENT_DOC: &str = "comment.doc";
pub const PUNCTUATION: &str = "punctuation";
pub const PUNCTUATION_BRACKET: &str = "punctuation.bracket";
pub const PUNCTUATION_DELIMITER: &str = "punctuation.delimiter";
pub const OPERATOR: &str = "operator";
pub const DIAGNOSTIC_ERROR: &str = "diagnostic.error";
pub const DIAGNOSTIC_WARNING: &str = "diagnostic.warning";
pub const DIAGNOSTIC_INFO: &str = "diagnostic.info";
pub const DIAGNOSTIC_HINT: &str = "diagnostic.hint";
pub const NAMESPACE: &str = "namespace";
pub const CONSTRUCTOR: &str = "constructor";
pub const LABEL: &str = "label";
pub const ATTRIBUTE: &str = "attribute";
pub const TAG: &str = "tag";
pub const MARKUP_HEADING: &str = "markup.heading";
pub const MARKUP_BOLD: &str = "markup.bold";
pub const MARKUP_ITALIC: &str = "markup.italic";
pub const MARKUP_STRIKETHROUGH: &str = "markup.strikethrough";
pub const MARKUP_LINK: &str = "markup.link";
pub const MARKUP_LINK_URL: &str = "markup.link.url";
pub const MARKUP_LIST: &str = "markup.list";
pub const MARKUP_RAW: &str = "markup.raw";
pub const MARKUP_RAW_INLINE: &str = "markup.raw.inline";
pub const EMBEDDED: &str = "embedded";
pub const SPECIAL: &str = "special";
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Annotation {
pub start_byte: usize,
pub end_byte: usize,
pub category: HighlightCategory,
}
impl Annotation {
#[must_use]
pub const fn new(start_byte: usize, end_byte: usize, category: HighlightCategory) -> Self {
Self {
start_byte,
end_byte,
category,
}
}
#[must_use]
pub const fn len(&self) -> usize {
self.end_byte - self.start_byte
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.start_byte == self.end_byte
}
#[must_use]
pub const fn overlaps(&self, range: &Range<usize>) -> bool {
self.start_byte < range.end && self.end_byte > range.start
}
#[must_use]
pub const fn contains(&self, byte: usize) -> bool {
self.start_byte <= byte && byte < self.end_byte
}
#[must_use]
pub const fn byte_range(&self) -> Range<usize> {
self.start_byte..self.end_byte
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SyntaxContext {
Code,
String,
Comment,
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Display for SyntaxContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Code => f.write_str("code"),
Self::String => f.write_str("string"),
Self::Comment => f.write_str("comment"),
}
}
}
#[cfg(test)]
#[path = "highlight_tests.rs"]
mod tests;