feat(printer): rename default printer and consistify some naming conventions with printing

BREAKING CHANGE: This is a significant API break.
This commit is contained in:
Kat Marchán 2021-08-21 22:52:06 -07:00
parent e980b72373
commit aafa4a3de1
No known key found for this signature in database
GPG Key ID: AEB529C08A3C7E9E
6 changed files with 113 additions and 51 deletions

View File

@ -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<dyn SpanContents + 'a>, Vec<Line>), 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);

View File

@ -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<Box<dyn DiagnosticReportPrinter + Send + Sync + 'stati
OnceCell::new();
/// Set the global [DiagnosticReportPrinter] that will be used when you report
/// using [DiagnosticReport].
pub fn set_reporter(
/// using [crate::DiagnosticReport].
pub fn set_printer(
reporter: impl DiagnosticReportPrinter + Send + Sync + 'static,
) -> 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<dyn DiagnosticReportPrinter + Send + Sync + 'sta
atty::is(Stream::Stdout) && atty::is(Stream::Stderr) && !ci_info::is_ci()
};
if fancy {
Box::new(DefaultReportPrinter {
theme: MietteTheme::default(),
Box::new(GraphicalReportPrinter {
theme: GraphicalTheme::default(),
})
} else {
Box::new(NarratableReportPrinter)
@ -55,9 +54,9 @@ fn get_default_printer() -> Box<dyn DiagnosticReportPrinter + Send + Sync + 'sta
}
/// Literally what it says on the tin.
pub struct JokeReporter;
pub struct JokePrinter;
impl DiagnosticReportPrinter for JokeReporter {
impl DiagnosticReportPrinter for JokePrinter {
fn debug(&self, diagnostic: &(dyn Diagnostic), f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
return fmt::Debug::fmt(diagnostic, f);

View File

@ -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 {

View File

@ -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<Style>,
}
@ -57,7 +93,8 @@ fn style() -> Style {
Style::new()
}
impl MietteStyles {
impl ThemeStyles {
/// ANSI color-based styles.
pub fn ansi() -> Self {
Self {
error: style().red(),
@ -74,6 +111,7 @@ impl MietteStyles {
}
}
/// No styling. Just regular ol' monochrome.
pub fn none() -> Self {
Self {
error: style(),
@ -88,9 +126,13 @@ impl MietteStyles {
}
// ---------------------------------------
// All code below here was taken from ariadne here:
// Most of these characters were taken from
// https://github.com/zesterer/ariadne/blob/e3cb394cb56ecda116a0a1caecd385a49e7f6662/src/draw.rs
pub struct MietteCharacters {
/// Characters to be used when drawing when using [crate::GraphicalReportPrinter].
#[allow(missing_docs)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ThemeCharacters {
pub hbar: char,
pub vbar: char,
pub xbar: char,
@ -121,7 +163,8 @@ pub struct MietteCharacters {
pub point_right: char,
}
impl MietteCharacters {
impl ThemeCharacters {
/// Fancy unicode-based graphical elements.
pub fn unicode() -> Self {
Self {
hbar: '',
@ -149,6 +192,7 @@ impl MietteCharacters {
}
}
/// ASCII-art-based graphical elements. Works well on older terminals.
pub fn ascii() -> Self {
Self {
hbar: '-',

View File

@ -1,5 +1,5 @@
use miette::{
DefaultReportPrinter, Diagnostic, DiagnosticReport, MietteError, MietteTheme,
GraphicalReportPrinter, Diagnostic, DiagnosticReport, MietteError, GraphicalTheme,
NarratableReportPrinter, SourceSpan,
};
use thiserror::Error;
@ -8,7 +8,7 @@ fn fmt_report(diag: DiagnosticReport) -> String {
let mut out = String::new();
// Mostly for dev purposes.
if std::env::var("STYLE").is_ok() {
DefaultReportPrinter::new_themed(MietteTheme::unicode())
GraphicalReportPrinter::new_themed(GraphicalTheme::unicode())
.render_report(&mut out, diag.inner())
.unwrap();
} else {

View File

@ -1,5 +1,5 @@
use miette::{
DefaultReportPrinter, Diagnostic, DiagnosticReport, MietteError, MietteTheme,
GraphicalReportPrinter, Diagnostic, DiagnosticReport, MietteError, GraphicalTheme,
NarratableReportPrinter, SourceSpan,
};
use thiserror::Error;
@ -8,7 +8,7 @@ fn fmt_report(diag: DiagnosticReport) -> String {
let mut out = String::new();
// Mostly for dev purposes.
if std::env::var("STYLE").is_ok() {
DefaultReportPrinter::new_themed(MietteTheme::unicode())
GraphicalReportPrinter::new_themed(GraphicalTheme::unicode())
.render_report(&mut out, diag.inner())
.unwrap();
} else if std::env::var("NARRATED").is_ok() {
@ -16,7 +16,7 @@ fn fmt_report(diag: DiagnosticReport) -> String {
.render_report(&mut out, diag.inner())
.unwrap();
} else {
DefaultReportPrinter::new_themed(MietteTheme::unicode_nocolor())
GraphicalReportPrinter::new_themed(GraphicalTheme::unicode_nocolor())
.render_report(&mut out, diag.inner())
.unwrap();
};