vle 1.22.0

Very Little Editor - an exercise in minimalist text editing
// Copyright 2026 Brian Langenberger
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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))
        }))
    }
}