atac 0.11.2

Arguably a Terminal API Client. Feature-full, free, open-source, offline and account-less.
use std::sync::{Arc, RwLock};

use ratatui::prelude::Color;
use ratatui::style::Style;
use ratatui::text::{Line, Span};
use syntect::easy::HighlightLines;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;

pub struct SyntaxHighlighting {
    pub syntax_set: SyntaxSet,
    pub theme_set: ThemeSet,
    pub last_highlighted: Arc<RwLock<Option<Vec<Vec<(String, Color)>>>>>
}

impl SyntaxHighlighting {
    pub fn highlight(&self, string: &'_ str, extension: &str) {
        let syntax = match self.syntax_set.find_syntax_by_extension(extension) {
            None => {
                *self.last_highlighted.write().unwrap() = None;
                return;
            }
            Some(syntax) => syntax
        };
        
        let mut highlight = HighlightLines::new(syntax, &self.theme_set.themes["base16-ocean.dark"]);

        let mut lines: Vec<Vec<(String, Color)>> = vec![];
        
        for line in string.lines() {
            let result = highlight.highlight_line(line, &self.syntax_set).unwrap();

            let mut highlighted_line: Vec<(String, Color)> = vec![];

            for &(ref style, text) in result.iter() {
                highlighted_line.push((text.to_string(), Color::Rgb(style.foreground.r, style.foreground.g, style.foreground.b)));
            }

            lines.push(highlighted_line)
        }
        
        let mut last_highlighted = self.last_highlighted.write().unwrap();
        *last_highlighted = Some(lines);
    }
}

pub fn last_highlighted_to_lines<'a>(last_highlighted: Vec<Vec<(String, Color)>>) -> Vec<Line<'a>> {
    let mut lines: Vec<Line> = vec![];

    for highlighted_line in last_highlighted {
        let mut spans: Vec<Span> = vec![];

        for (text, color) in highlighted_line {
            spans.push(Span::raw(text).style(Style::new().fg(color.clone())))
        }

        let line = Line::from(spans);
        lines.push(line);
    }

    return lines;
}