use mlua::{FromLua, IntoLua}; use ratatui::{style::Color, text::Span}; use tree_sitter_highlight::Highlight; use crate::config::theme::style::Style; pub(super) static HIGHLIGHT_NAMES: [&str; 29] = [ "attribute", "boolean", "comment", "conditional", "constant", "constant.builtin", "constructor", "field", "function", "function.builtin", "function.call", "keyword", "keyword.function", "keyword.operator", "keyword.return", "label", "method", "method.call", "number", "operator", "parameter", "preproc", "punctuation.bracket", "punctuation.delimiter", "repeat", "string", "string.escape", "variable", "variable.builtin", ]; #[derive(Default, Debug, Clone)] pub struct HighlightTheme { theme: [Style; 29], } impl HighlightTheme { pub const fn new() -> Self { Self { theme: [ Style::new().fg(Color::White), // attribute Style::new().fg(Color::White), // boolean Style::new().fg(Color::White), // comment Style::new().fg(Color::White), // conditional Style::new().fg(Color::White), // constant Style::new().fg(Color::White), // constant.builtin Style::new().fg(Color::White), // constructor Style::new().fg(Color::White), // field Style::new().fg(Color::White), // function Style::new().fg(Color::White), // function.builtin Style::new().fg(Color::White), // function.call Style::new().fg(Color::White), // keyword Style::new().fg(Color::White), // keyword.function Style::new().fg(Color::White), // keyword.operator Style::new().fg(Color::White), // keyword.return Style::new().fg(Color::White), // label Style::new().fg(Color::White), // method Style::new().fg(Color::White), // method.call Style::new().fg(Color::White), // number Style::new().fg(Color::White), // operator Style::new().fg(Color::White), // parameter Style::new().fg(Color::White), // preproc Style::new().fg(Color::White), // punctuation.bracket Style::new().fg(Color::White), // punctuation.delimiter Style::new().fg(Color::White), // repeat Style::new().fg(Color::White), // string Style::new().fg(Color::White), // string.escape Style::new().fg(Color::White), // variable Style::new().fg(Color::White), // variable.builtin ], } } pub fn highlight<'a>(&'a self, hl: Option, span: Span<'a>) -> Span<'a> { if let Some(hl) = hl { self.theme[hl.0].apply(span) } else { span } } } impl<'lua> IntoLua<'lua> for HighlightTheme { fn into_lua( self, lua: &'lua mlua::prelude::Lua, ) -> mlua::prelude::LuaResult> { let table = lua.create_table()?; for (i, names) in HIGHLIGHT_NAMES.iter().enumerate() { table.set(names.replace('.', "_"), self.theme[i])? } table.into_lua(lua) } } impl<'lua> FromLua<'lua> for HighlightTheme { fn from_lua( value: mlua::prelude::LuaValue<'lua>, _lua: &'lua mlua::prelude::Lua, ) -> mlua::prelude::LuaResult { let mut theme = HighlightTheme::default(); if value.is_table() { let table = value.as_table().unwrap(); for (i, names) in HIGHLIGHT_NAMES.iter().enumerate() { if let Ok(style) = table.get(names.replace('.', "_")) { theme.theme[i] = style; } } Ok(theme) } else { Err(mlua::prelude::LuaError::runtime( "failed to parse HighlightTheme", )) } } }