use crate::syntax::{Highlight, Highlighter, color};
use logos::Logos;
use ratatui::style::Color;
#[derive(Logos, Debug)]
#[logos(skip r"[ \t\n]+")]
enum MakefileToken {
#[regex(r"\$+[{(][[:alnum:]_-]+[})]")]
Variable,
#[regex(r" (:?:|\+|\?)?= ")]
Assignment,
#[regex("#.*", allow_greedy = true)]
Comment,
}
impl TryFrom<MakefileToken> for Highlight {
type Error = ();
fn try_from(t: MakefileToken) -> Result<Highlight, ()> {
match t {
MakefileToken::Variable => Ok(Color::Cyan.into()),
MakefileToken::Assignment => Ok(Color::Red.into()),
MakefileToken::Comment => Ok(color::COMMENT),
}
}
}
#[derive(Debug)]
pub struct Makefile;
impl std::fmt::Display for Makefile {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
"Makefile".fmt(f)
}
}
impl crate::syntax::Syntax for Makefile {
fn initialize(
&self,
_rope: &ropey::Rope,
_viewport_line: usize,
_viewport_height: u16,
) -> Box<dyn Highlighter> {
Box::new(MakefileHighlighter)
}
fn initialize_find(&self) -> Box<dyn Highlighter> {
Box::new(MakefileHighlighter)
}
fn tabs_required(&self) -> bool {
true
}
}
struct MakefileHighlighter;
impl Highlighter for MakefileHighlighter {
fn highlight<'s>(
&'s mut self,
line: &'s str,
) -> Box<dyn Iterator<Item = (Highlight, std::ops::Range<usize>)> + 's> {
Box::new(MakefileToken::lexer(line).spanned().filter_map(|(t, r)| {
t.ok()
.and_then(|t| Highlight::try_from(t).ok())
.map(|c| (c, r))
}))
}
}