// Port of rich/highlighter.py.
///|
/// A highlighter applies styles to text in place.
pub(open) trait Highlighter {
fn highlight(Self, Text) -> Unit raise
}
///|
/// Highlight a string or a copy of a Text (upstream `highlighter(text)`).
pub fn &Highlighter::apply(self : &Highlighter, text : &IntoText) -> Text raise {
let highlight_text = match text.into_text_type() {
Str(s) => Text::new(text=s)
Text(t) => t.copy()
}
self.highlight(highlight_text)
highlight_text
}
///|
/// A highlighter that doesn't highlight.
pub struct NullHighlighter {}
///|
pub fn NullHighlighter::new() -> NullHighlighter {
NullHighlighter::{ }
}
///|
pub impl Highlighter for NullHighlighter with fn highlight(_self, _text) {
()
}
///|
/// Applies highlighting from a list of regular expressions, where group
/// names are translated to styles prefixed by `base_style`.
pub struct RegexHighlighter {
highlights : Array[@regex.Regex]
base_style : String
}
///|
/// Create a highlighter from regular expressions (Python `re` syntax).
pub fn RegexHighlighter::new(
highlights : Array[String],
base_style? : String = "",
) -> RegexHighlighter raise @regex.RegexError {
let compiled = []
for pattern in highlights {
compiled.push(compile_regex(pattern))
}
{ highlights: compiled, base_style, }
}
///|
pub impl Highlighter for RegexHighlighter with fn highlight(self, text) {
for re in self.highlights {
text.highlight_regex(re, style_prefix=self.base_style) |> ignore
}
}
///|
fn must_regex_highlighter(
highlights : Array[String],
base_style : String,
) -> RegexHighlighter {
RegexHighlighter::new(highlights, base_style~) catch {
_ => abort("invalid built-in highlighter regex")
}
}
///|
let repr_highlights : Array[String] = [
"(?P<)(?P[-\\w.:|]*)(?P[\\w\\W]*)(?P>)",
"(?P[\\w_]{1,50})=(?P\"?[\\w_]+\"?)?",
"(?P[][{}()])",
[
"(?P[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})", "(?P([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})",
"(?P(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\\.){3}[0-9A-Fa-f]{4})",
"(?P(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\\.){2}[0-9A-Fa-f]{4})",
"(?P[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})",
"(?P[\\w.]*?)\\(", "\\b(?PTrue)\\b|\\b(?PFalse)\\b|\\b(?PNone)\\b",
"(?P\\.\\.\\.)", "(?P(?(?\\B(/[-\\w._+]+)*\\/)(?P[-\\w._+]*)?",
"(?b?'''.*?(?(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#~@]*)",
].join("|"),
]
///|
let repr_highlighter_instance : RegexHighlighter = must_regex_highlighter(
repr_highlights, "repr.",
)
///|
/// Highlights the text typically produced from `__repr__` methods.
pub struct ReprHighlighter {
priv inner : RegexHighlighter
}
///|
pub fn ReprHighlighter::new() -> ReprHighlighter {
{ inner: repr_highlighter_instance, }
}
///|
pub impl Highlighter for ReprHighlighter with fn highlight(self, text) {
self.inner.highlight(text)
}
///|
let json_str_pattern : String = "(?b?\\\".*?(?[\\{\\[\\(\\)\\]\\}])", "\\b(?Ptrue)\\b|\\b(?Pfalse)\\b|\\b(?Pnull)\\b",
"(?P(? JSONHighlighter {
JSONHighlighter::{ }
}
///|
pub impl Highlighter for JSONHighlighter with fn highlight(_self, text) {
json_highlighter_base.highlight(text)
let plain = text.plain()
let re = compile_regex(json_str_pattern)
for m in re.find_all(plain) {
let start = m.start()
let end = m.end()
let mut cursor = end
while cursor < plain.length() {
let c = plain[cursor]
cursor += 1
if c == ':' {
text.spans().push({ start, end, style: Def("json.key"), })
} else if c == ' ' || c == '\n' || c == '\r' || c == '\t' {
continue
}
break
}
}
}
///|
let iso8601_highlights : Array[String] = [
"^(?P[0-9]{4})-(?P1[0-2]|0[1-9])$", "^(?P(?P[0-9]{4})(?P1[0-2]|0[1-9])(?P3[01]|0[1-9]|[12][0-9]))$",
"^(?P(?P[0-9]{4})-?(?P36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$",
"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9]))$", "^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9])-?(?P[1-7]))$",
"^(?P