mirror of https://github.com/zkat/miette.git
117 lines
4.3 KiB
Rust
117 lines
4.3 KiB
Rust
//! This module provides a trait for creating custom syntax highlighters that
|
|
//! highlight [`Diagnostic`](crate::Diagnostic) source code with ANSI escape
|
|
//! sequences when rendering with the [`GraphicalReportHighlighter`](crate::GraphicalReportHandler).
|
|
//!
|
|
//! It also provides built-in highlighter implementations that you can use out of the box.
|
|
//! By default, there are no syntax highlighters exported by miette
|
|
//! (except for the no-op [`BlankHighlighter`]).
|
|
//! To enable support for specific highlighters, you should enable their associated feature flag.
|
|
//!
|
|
//! Currently supported syntax highlighters and their feature flags:
|
|
//! * `syntect-highlighter` - Enables [`syntect`](https://docs.rs/syntect/latest/syntect/) syntax highlighting support via the [`SyntectHighlighter`]
|
|
//!
|
|
|
|
use std::{ops::Deref, sync::Arc};
|
|
|
|
use crate::SourceCode;
|
|
use owo_colors::Styled;
|
|
|
|
#[cfg(feature = "syntect-highlighter")]
|
|
pub use self::syntect::*;
|
|
pub use blank::*;
|
|
|
|
mod blank;
|
|
#[cfg(feature = "syntect-highlighter")]
|
|
mod syntect;
|
|
|
|
/// A syntax highlighter for highlighting miette [SourceCode] snippets.
|
|
pub trait Highlighter {
|
|
/// Creates a new [HighlighterState] to begin parsing and highlighting
|
|
/// a [SourceCode] snippet.
|
|
///
|
|
/// The [GraphicalReportHandler](crate::GraphicalReportHandler) will call
|
|
/// this method at the start of rendering a [Diagnostic](crate::Diagnostic).
|
|
///
|
|
/// The source is provided as input only so that the Highlighter can detect
|
|
/// language syntax and make other initialization decisions prior
|
|
/// to highlighting, but it is not intended that the Highlighter begin
|
|
/// highlighting at this point. The returned [HighlighterState] is
|
|
/// responsible for the actual rendering.
|
|
fn start_highlighter_state<'h>(
|
|
&'h self,
|
|
source: &dyn SourceCode,
|
|
) -> Box<dyn HighlighterState + 'h>;
|
|
}
|
|
|
|
/// A stateful highlighter that incrementally highlights lines of a particular
|
|
/// source code.
|
|
///
|
|
/// The [GraphicalReportHandler](crate::GraphicalReportHandler)
|
|
/// will create a highlighter state by calling
|
|
/// [start_highlighter_state](Highlighter::start_highlighter_state) at the
|
|
/// start of rendering, then it will iteratively call
|
|
/// [highlight_line](HighlighterState::highlight_line) to render individual
|
|
/// highlighted lines. This allows [Highlighter] implementations to maintain
|
|
/// mutable parsing and highlighting state.
|
|
pub trait HighlighterState {
|
|
/// Highlight an individual line from the source code by returning a vector of [Styled]
|
|
/// regions.
|
|
fn highlight_line<'s>(&mut self, line: &'s str) -> Vec<Styled<&'s str>>;
|
|
}
|
|
|
|
/// Arcified trait object for Highlighter. Used internally by [GraphicalReportHandler]
|
|
///
|
|
/// Wrapping the trait object in this way allows us to implement Debug and Clone.
|
|
#[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 is_terminal::IsTerminal;
|
|
match std::env::var("NO_COLOR") {
|
|
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
|
|
//TODO: should use ANSI styling instead of 24-bit truecolor here
|
|
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 {
|
|
return 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
|
|
}
|
|
}
|