use std::{ops::Deref, sync::Arc};
use crate::SpanContents;
use owo_colors::Styled;
#[cfg(feature = "syntect-highlighter")]
pub use self::syntect::*;
pub use blank::*;
mod blank;
#[cfg(feature = "syntect-highlighter")]
mod syntect;
pub trait Highlighter {
fn start_highlighter_state<'h>(
&'h self,
source: &dyn SpanContents<'_>,
) -> Box<dyn HighlighterState + 'h>;
}
pub trait HighlighterState {
fn highlight_line<'s>(&mut self, line: &'s str) -> Vec<Styled<&'s str>>;
}
#[derive(Clone)]
#[repr(transparent)]
pub(crate) struct MietteHighlighter(Arc<dyn Highlighter + Send + Sync>);
impl MietteHighlighter {
pub(crate) fn nocolor() -> Self {
Self::from(BlankHighlighter)
}
#[cfg(feature = "syntect-highlighter")]
pub(crate) fn syntect_truecolor() -> Self {
Self::from(SyntectHighlighter::default())
}
}
impl Default for MietteHighlighter {
#[cfg(feature = "syntect-highlighter")]
fn default() -> Self {
use std::io::IsTerminal;
match std::env::var("NO_COLOR") {
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
Self(Arc::new(SyntectHighlighter::default()))
}
Ok(string) if string != "0" => MietteHighlighter::nocolor(),
_ => Self(Arc::new(SyntectHighlighter::default())),
}
}
#[cfg(not(feature = "syntect-highlighter"))]
fn default() -> Self {
MietteHighlighter::nocolor()
}
}
impl<T: Highlighter + Send + Sync + 'static> From<T> for MietteHighlighter {
fn from(value: T) -> Self {
Self(Arc::new(value))
}
}
impl std::fmt::Debug for MietteHighlighter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "MietteHighlighter(...)")
}
}
impl Deref for MietteHighlighter {
type Target = dyn Highlighter + Send + Sync;
fn deref(&self) -> &Self::Target {
&*self.0
}
}