use nalgebra_glm::Vec4;
use syntect::easy::HighlightLines;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;
use crate::ecs::world::World;
pub struct SyntaxHighlighter {
syntax_set: SyntaxSet,
theme_set: ThemeSet,
}
impl SyntaxHighlighter {
fn new() -> Self {
Self {
syntax_set: SyntaxSet::load_defaults_newlines(),
theme_set: ThemeSet::load_defaults(),
}
}
pub fn highlight(&self, text: &str, language: &str) -> Vec<Option<Vec4>> {
let syntax = self
.syntax_set
.find_syntax_by_token(language)
.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
let theme = &self.theme_set.themes["base16-mocha.dark"];
let mut highlighter = HighlightLines::new(syntax, theme);
let mut colors = Vec::new();
for line in LinesWithEndings::from(text) {
let ranges = highlighter
.highlight_line(line, &self.syntax_set)
.unwrap_or_default();
for (style, fragment) in ranges {
let r = style.foreground.r as f32 / 255.0;
let g = style.foreground.g as f32 / 255.0;
let b = style.foreground.b as f32 / 255.0;
let a = style.foreground.a as f32 / 255.0;
let color = Some(Vec4::new(r, g, b, a));
for character in fragment.chars() {
if character != '\n' {
colors.push(color);
}
}
}
}
colors
}
}
pub fn highlight_text_area(world: &mut World, text: &str, language: &str, text_slot: usize) {
if world.resources.retained_ui.syntax_highlighter.is_none() {
world.resources.retained_ui.syntax_highlighter = Some(SyntaxHighlighter::new());
}
let highlighter = world
.resources
.retained_ui
.syntax_highlighter
.as_ref()
.unwrap();
let colors = highlighter.highlight(text, language);
world
.resources
.retained_ui
.text_slot_character_colors
.insert(text_slot, colors);
}