mod theme;
mod treesitter;
pub use theme::{HighlightTheme, SolarizedTheme};
pub use treesitter::TreeSitterHighlighter;
use ratatui::text::Line;
pub trait Highlighter {
fn highlight<'a>(&self, source: &'a str) -> Vec<Line<'a>>;
fn highlight_incremental<'a>(
&mut self,
source: &'a str,
start_byte: usize,
old_end_byte: usize,
new_end_byte: usize,
) -> Vec<Line<'a>>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HighlightCapture {
Key,
String,
Number,
Boolean,
Null,
Comment,
Punctuation,
Verb,
TaskId,
Template,
McpServer,
Error,
}
impl HighlightCapture {
pub fn from_name(name: &str) -> Option<Self> {
match name {
"keyword" | "key" | "property" => Some(Self::Key),
"string" => Some(Self::String),
"number" => Some(Self::Number),
"constant.builtin" | "boolean" => Some(Self::Boolean),
"constant" | "null" => Some(Self::Null),
"comment" => Some(Self::Comment),
"punctuation" | "punctuation.bracket" | "punctuation.delimiter" => {
Some(Self::Punctuation)
}
"function" | "verb" => Some(Self::Verb),
"label" | "task_id" => Some(Self::TaskId),
"embedded" | "template" => Some(Self::Template),
"namespace" | "mcp_server" => Some(Self::McpServer),
"error" => Some(Self::Error),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_capture_from_name() {
assert_eq!(
HighlightCapture::from_name("keyword"),
Some(HighlightCapture::Key)
);
assert_eq!(
HighlightCapture::from_name("string"),
Some(HighlightCapture::String)
);
assert_eq!(
HighlightCapture::from_name("number"),
Some(HighlightCapture::Number)
);
assert_eq!(
HighlightCapture::from_name("constant.builtin"),
Some(HighlightCapture::Boolean)
);
assert_eq!(
HighlightCapture::from_name("comment"),
Some(HighlightCapture::Comment)
);
assert_eq!(
HighlightCapture::from_name("function"),
Some(HighlightCapture::Verb)
);
assert_eq!(HighlightCapture::from_name("unknown"), None);
}
}