use ratatui::style::Color;
use syntect::easy::HighlightLines;
use syntect::highlighting::Theme;
use syntect::parsing::{SyntaxReference, SyntaxSet};
use two_face::theme::EmbeddedThemeName;
pub struct Highlighter {
ps: SyntaxSet,
theme: Theme,
}
impl Highlighter {
pub fn new() -> Self {
let ps = two_face::syntax::extra_no_newlines();
let theme = two_face::theme::extra()
.get(EmbeddedThemeName::MonokaiExtendedBright)
.clone();
Highlighter { ps, theme }
}
pub fn syntax_for(&self, path: &str) -> &SyntaxReference {
let p = std::path::Path::new(path);
let ext = p.extension().and_then(|e| e.to_str()).unwrap_or("");
self.ps
.find_syntax_by_extension(ext)
.or_else(|| {
let name = p.file_name().and_then(|n| n.to_str()).unwrap_or("");
self.ps.find_syntax_by_token(name)
})
.unwrap_or_else(|| self.ps.find_syntax_plain_text())
}
pub fn line(&self, syntax: &SyntaxReference, text: &str) -> Vec<(Color, String)> {
let mut h = HighlightLines::new(syntax, &self.theme);
match h.highlight_line(text, &self.ps) {
Ok(ranges) => ranges
.into_iter()
.map(|(st, s)| {
let c = st.foreground;
(Color::Rgb(c.r, c.g, c.b), s.to_string())
})
.collect(),
Err(_) => vec![(Color::Gray, text.to_string())],
}
}
}