From aafa4a3de1298dd8e7625138d09a408ff3579d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Sat, 21 Aug 2021 22:52:06 -0700 Subject: [PATCH] feat(printer): rename default printer and consistify some naming conventions with printing BREAKING CHANGE: This is a significant API break. --- ...efault_printer.rs => graphical_printer.rs} | 46 ++++++---- src/printer/mod.rs | 23 +++-- src/printer/narratable_printer.rs | 1 + src/printer/theme.rs | 84 ++++++++++++++----- tests/narrated.rs | 4 +- tests/printer.rs | 6 +- 6 files changed, 113 insertions(+), 51 deletions(-) rename src/printer/{default_printer.rs => graphical_printer.rs} (92%) diff --git a/src/printer/default_printer.rs b/src/printer/graphical_printer.rs similarity index 92% rename from src/printer/default_printer.rs rename to src/printer/graphical_printer.rs index 498a9e3..a63f58c 100644 --- a/src/printer/default_printer.rs +++ b/src/printer/graphical_printer.rs @@ -8,34 +8,52 @@ use crate::protocol::{Diagnostic, DiagnosticReportPrinter, DiagnosticSnippet, Se use crate::{SourceSpan, SpanContents}; /** -Reference implementation of the [DiagnosticReportPrinter] trait. This is generally -good enough for simple use-cases, and is the default one installed with `miette`, -but you might want to implement your own if you want custom reporting for your -tool or app. +A [DiagnosticReportPrinter] that displays a given [crate::DiagnosticReport] in a quasi-graphical way, using terminal colors, unicode drawing characters, and other such things. + +This is the default reporter bundled with `miette`. + +This printer can be customized by using `new_themed()` and handing it a [GraphicalTheme] of your own creation (or using one of its own defaults!) + +See [crate::set_printer] for more details on customizing your global printer. + +## Example + +``` +use miette::{GraphicalReportPrinter, GraphicalTheme}; +miette::set_printer(GraphicalReportPrinter::new_themed(GraphicalTheme::unicode_nocolor())); +``` */ -pub struct DefaultReportPrinter { - pub(crate) theme: MietteTheme, +#[derive(Debug, Clone)] +pub struct GraphicalReportPrinter { + pub(crate) theme: GraphicalTheme, } -impl DefaultReportPrinter { +impl GraphicalReportPrinter { + /// Create a new [GraphicalReportPrinter] with the default + /// [GraphicalTheme]. This will use both unicode characters and colors. pub fn new() -> Self { Self { - theme: MietteTheme::default(), + theme: GraphicalTheme::default(), } } - pub fn new_themed(theme: MietteTheme) -> Self { + ///Create a new [GraphicalReportPrinter] with a given [GraphicalTheme]. + pub fn new_themed(theme: GraphicalTheme) -> Self { Self { theme } } } -impl Default for DefaultReportPrinter { +impl Default for GraphicalReportPrinter { fn default() -> Self { Self::new() } } -impl DefaultReportPrinter { +impl GraphicalReportPrinter { + /// Render a [Diagnostic]. This function is mostly internal and meant to + /// be called by the toplevel [DiagnosticReportPrinter] handler, but is + /// made public to make it easier (possible) to test in isolation from + /// global state. pub fn render_report( &self, f: &mut impl fmt::Write, @@ -116,7 +134,7 @@ impl DefaultReportPrinter { Ok(()) } - fn render_snippet(&self, f: &mut impl fmt::Write, snippet: &DiagnosticSnippet) -> fmt::Result { + fn render_snippet(&self, f: &mut impl fmt::Write, snippet: &DiagnosticSnippet<'_>) -> fmt::Result { let (contents, lines) = self.get_lines(snippet)?; // Highlights are the bits we're going to underline in our overall @@ -408,7 +426,7 @@ impl DefaultReportPrinter { fn get_lines<'a>( &'a self, - snippet: &'a DiagnosticSnippet, + snippet: &'a DiagnosticSnippet<'_>, ) -> Result<(Box, Vec), fmt::Error> { let context_data = snippet .source @@ -463,7 +481,7 @@ impl DefaultReportPrinter { } } -impl DiagnosticReportPrinter for DefaultReportPrinter { +impl DiagnosticReportPrinter for GraphicalReportPrinter { fn debug(&self, diagnostic: &(dyn Diagnostic), f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { return fmt::Debug::fmt(diagnostic, f); diff --git a/src/printer/mod.rs b/src/printer/mod.rs index b8d5415..d3c50e7 100644 --- a/src/printer/mod.rs +++ b/src/printer/mod.rs @@ -1,6 +1,5 @@ /*! -Basic reporter for Diagnostics. Probably good enough for most use-cases, -but largely meant to be an example. +Reporters included with `miette`. */ use std::fmt; @@ -10,11 +9,11 @@ use once_cell::sync::OnceCell; use crate::protocol::{Diagnostic, DiagnosticReportPrinter, Severity}; use crate::MietteError; -pub use default_printer::*; +pub use graphical_printer::*; pub use narratable_printer::*; pub use theme::*; -mod default_printer; +mod graphical_printer; mod narratable_printer; mod theme; @@ -22,8 +21,8 @@ static REPORTER: OnceCell Result<(), MietteError> { REPORTER @@ -31,9 +30,9 @@ pub fn set_reporter( .map_err(|_| MietteError::SetPrinterFailure) } -/// Used by [DiagnosticReport] to fetch the reporter that will be used to +/// Used by [crate::DiagnosticReport] to fetch the reporter that will be used to /// print stuff out. -pub fn get_reporter() -> &'static (dyn DiagnosticReportPrinter + Send + Sync + 'static) { +pub(crate) fn get_printer() -> &'static (dyn DiagnosticReportPrinter + Send + Sync + 'static) { &**REPORTER.get_or_init(get_default_printer) } @@ -46,8 +45,8 @@ fn get_default_printer() -> Box Box) -> fmt::Result { if f.alternate() { return fmt::Debug::fmt(diagnostic, f); diff --git a/src/printer/narratable_printer.rs b/src/printer/narratable_printer.rs index b6398eb..6e99f3f 100644 --- a/src/printer/narratable_printer.rs +++ b/src/printer/narratable_printer.rs @@ -10,6 +10,7 @@ good enough for simple use-cases, and is the default one installed with `miette` but you might want to implement your own if you want custom reporting for your tool or app. */ +#[derive(Debug, Clone)] pub struct NarratableReportPrinter; impl NarratableReportPrinter { diff --git a/src/printer/theme.rs b/src/printer/theme.rs index b27b358..89cecde 100644 --- a/src/printer/theme.rs +++ b/src/printer/theme.rs @@ -1,55 +1,91 @@ use atty::Stream; use owo_colors::Style; -pub struct MietteTheme { - pub characters: MietteCharacters, - pub styles: MietteStyles, +/** +Theme used by [crate::GraphicalReportPrinter] to render fancy [crate::Diagnostic] reports. + +A theme consists of two things: the set of characters to be used for drawing, +and the [owo_colors::Style]s to be used to paint various items. + +You can create your own custom graphical theme using this type, or you can use +one of the predefined ones using the methods below. +*/ +#[derive(Debug, Clone)] +pub struct GraphicalTheme { + /// Characters to be used for drawing. + pub characters: ThemeCharacters, + /// Styles to be used for painting. + pub styles: ThemeStyles, } -impl MietteTheme { - pub fn basic() -> Self { +impl GraphicalTheme { + /// ASCII-art-based graphical drawing, with ANSI styling. + pub fn ascii() -> Self { Self { - characters: MietteCharacters::ascii(), - styles: MietteStyles::ansi(), + characters: ThemeCharacters::ascii(), + styles: ThemeStyles::ansi(), } } + + /// Graphical theme that draws using both ansi colors and unicode characters. pub fn unicode() -> Self { Self { - characters: MietteCharacters::unicode(), - styles: MietteStyles::ansi(), + characters: ThemeCharacters::unicode(), + styles: ThemeStyles::ansi(), } } + + /// Graphical theme that draws in monochrome, while still using unicode + /// characters. pub fn unicode_nocolor() -> Self { Self { - characters: MietteCharacters::unicode(), - styles: MietteStyles::none(), + characters: ThemeCharacters::unicode(), + styles: ThemeStyles::none(), } } + + /// A "basic" graphical theme that skips colors and unicode characters and + /// just does monochrome ascii art. If you want a completely non-graphical + /// rendering of your `Diagnostic`s, check out + /// [crate::NarratableReportPrinter], or write your own + /// [crate::DiagnosticReportPrinter]! pub fn none() -> Self { Self { - characters: MietteCharacters::ascii(), - styles: MietteStyles::none(), + characters: ThemeCharacters::ascii(), + styles: ThemeStyles::none(), } } } -impl Default for MietteTheme { +impl Default for GraphicalTheme { fn default() -> Self { match std::env::var("NO_COLOR") { - _ if !atty::is(Stream::Stdout) || !atty::is(Stream::Stderr) => Self::basic(), + _ if !atty::is(Stream::Stdout) || !atty::is(Stream::Stderr) => Self::ascii(), Ok(string) if string != "0" => Self::unicode_nocolor(), _ => Self::unicode(), } } } -pub struct MietteStyles { +/** +Styles for various parts of graphical rendering for the [crate::GraphicalReportPrinter]. +*/ +#[derive(Debug, Clone)] +pub struct ThemeStyles { + /// Style to apply to things highlighted as "error". pub error: Style, + /// Style to apply to things highlighted as "warning". pub warning: Style, + /// Style to apply to things highlighted as "advice". pub advice: Style, + /// Style to apply to the diagnostic code. pub code: Style, + /// Style to apply to the help text. pub help: Style, + /// Style to apply to the filename/source name. pub filename: Style, + /// Styles to cycle through (using `.iter().cycle()`), to render the lines + /// and text for diagnostic highlights. pub highlights: Vec