mirror of https://github.com/zkat/miette.git
feat(report): make a single big MietteHandler that can switch modes
BREAKING CHANGE: linkification option method on GraphicalReportHandler has been changed to .with_links(bool)
This commit is contained in:
parent
80036781cd
commit
4c2463f9ae
|
|
@ -21,6 +21,9 @@ ci_info = "0.14.2"
|
|||
textwrap = "0.14.2"
|
||||
term_size = "0.3.2"
|
||||
unicode-width = "0.1.8"
|
||||
supports-hyperlinks = "1.1.0"
|
||||
supports-color = "1.0.2"
|
||||
supports-unicode = "1.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
semver = "1.0.4"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use core::mem::ManuallyDrop;
|
|||
|
||||
use std::error::Error as StdError;
|
||||
|
||||
use atty::Stream;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
|
|
@ -27,7 +26,7 @@ pub use ReportHandler as EyreContext;
|
|||
#[allow(unreachable_pub)]
|
||||
pub use WrapErr as Context;
|
||||
|
||||
use crate::{Diagnostic, GraphicalReportHandler, NarratableReportHandler};
|
||||
use crate::{Diagnostic, MietteHandler};
|
||||
use error::ErrorImpl;
|
||||
|
||||
mod context;
|
||||
|
|
@ -88,19 +87,7 @@ fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler>
|
|||
}
|
||||
|
||||
fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler + 'static> {
|
||||
let fancy = if let Ok(string) = std::env::var("NO_COLOR") {
|
||||
string == "0"
|
||||
} else if let Ok(string) = std::env::var("CLICOLOR") {
|
||||
string != "0" || string == "1"
|
||||
} else {
|
||||
atty::is(Stream::Stdout) && atty::is(Stream::Stderr) && !ci_info::is_ci()
|
||||
};
|
||||
let size = term_size::dimensions().unwrap_or((80, 0)).0;
|
||||
if fancy {
|
||||
Box::new(GraphicalReportHandler::new().with_width(size))
|
||||
} else {
|
||||
Box::new(NarratableReportHandler)
|
||||
}
|
||||
Box::new(MietteHandler::new())
|
||||
}
|
||||
|
||||
impl dyn ReportHandler {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,206 @@
|
|||
use std::fmt;
|
||||
|
||||
use atty::Stream;
|
||||
|
||||
use crate::protocol::Diagnostic;
|
||||
use crate::GraphicalReportHandler;
|
||||
use crate::GraphicalTheme;
|
||||
use crate::NarratableReportHandler;
|
||||
use crate::ReportHandler;
|
||||
use crate::ThemeCharacters;
|
||||
use crate::ThemeStyles;
|
||||
|
||||
/**
|
||||
Create a custom [MietteHandler] from options.
|
||||
*/
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct MietteHandlerOpts {
|
||||
pub(crate) linkify: Option<bool>,
|
||||
pub(crate) width: Option<usize>,
|
||||
pub(crate) theme: Option<GraphicalTheme>,
|
||||
pub(crate) force_graphical: Option<bool>,
|
||||
pub(crate) force_narrated: Option<bool>,
|
||||
pub(crate) ansi_colors: Option<bool>,
|
||||
pub(crate) rgb_colors: Option<bool>,
|
||||
pub(crate) color: Option<bool>,
|
||||
pub(crate) unicode: Option<bool>,
|
||||
}
|
||||
|
||||
impl MietteHandlerOpts {
|
||||
/// Create a new [MietteHandlerOpts].
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// If true, specify whether the graphical handler will make codes be
|
||||
/// clickable links in supported terminals. Defaults to auto-detection
|
||||
/// based on known supported terminals.
|
||||
pub fn terminal_links(mut self, linkify: bool) -> Self {
|
||||
self.linkify = Some(linkify);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a graphical theme for the handler when rendering in graphical
|
||||
/// mode. Use [MietteHandlerOpts::force_graphical] to force graphical
|
||||
/// mode. This option overrides [MietteHandlerOpts::color].
|
||||
pub fn graphical_theme(mut self, theme: GraphicalTheme) -> Self {
|
||||
self.theme = Some(theme);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the width to wrap the report at. Defaults
|
||||
pub fn width(mut self, width: usize) -> Self {
|
||||
self.width = Some(width);
|
||||
self
|
||||
}
|
||||
|
||||
/// If true, colors will be used during graphical rendering. Actual color
|
||||
/// format will be auto-detected.
|
||||
pub fn color(mut self, color: bool) -> Self {
|
||||
self.color = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// If true, RGB colors will be used during graphical rendering.
|
||||
pub fn rgb_colors(mut self, color: bool) -> Self {
|
||||
self.rgb_colors = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// If true, forces unicode display for graphical output. If set to false,
|
||||
/// forces ASCII art display.
|
||||
pub fn unicode(mut self, unicode: bool) -> Self {
|
||||
self.unicode = Some(unicode);
|
||||
self
|
||||
}
|
||||
|
||||
/// If true, ANSI colors will be used during graphical rendering.
|
||||
pub fn ansi_colors(mut self, color: bool) -> Self {
|
||||
self.rgb_colors = Some(color);
|
||||
self
|
||||
}
|
||||
/// If true, graphical rendering will be used regardless of terminal
|
||||
/// detection.
|
||||
pub fn force_graphical(mut self, force: bool) -> Self {
|
||||
self.force_graphical = Some(force);
|
||||
self
|
||||
}
|
||||
|
||||
/// If true, forces use of the narrated renderer.
|
||||
pub fn force_narrated(mut self, force: bool) -> Self {
|
||||
self.force_narrated = Some(force);
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds a [MietteHandler] from this builder.
|
||||
pub fn build(self) -> MietteHandler {
|
||||
let graphical = self.is_graphical();
|
||||
let width = self.get_width();
|
||||
if !graphical {
|
||||
MietteHandler {
|
||||
inner: Box::new(NarratableReportHandler::new()),
|
||||
}
|
||||
} else {
|
||||
let linkify = self.use_links();
|
||||
let characters = match self.unicode {
|
||||
Some(true) => ThemeCharacters::unicode(),
|
||||
Some(false) => ThemeCharacters::ascii(),
|
||||
None if supports_unicode::on(Stream::Stderr) => ThemeCharacters::unicode(),
|
||||
None => ThemeCharacters::ascii(),
|
||||
};
|
||||
let styles = if self.rgb_colors == Some(true) {
|
||||
ThemeStyles::rgb()
|
||||
} else if self.ansi_colors == Some(true) {
|
||||
ThemeStyles::ansi()
|
||||
} else if let Some(colors) = supports_color::on(Stream::Stderr) {
|
||||
if colors.has_16m {
|
||||
ThemeStyles::rgb()
|
||||
} else {
|
||||
ThemeStyles::ansi()
|
||||
}
|
||||
} else if self.color == Some(true) {
|
||||
ThemeStyles::ansi()
|
||||
} else {
|
||||
ThemeStyles::none()
|
||||
};
|
||||
MietteHandler {
|
||||
inner: Box::new(
|
||||
GraphicalReportHandler::new()
|
||||
.with_width(width)
|
||||
.with_links(linkify)
|
||||
.with_theme(GraphicalTheme { characters, styles }),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_graphical(&self) -> bool {
|
||||
if let Some(force_narrated) = self.force_narrated {
|
||||
!force_narrated
|
||||
} else if let Some(force_graphical) = self.force_graphical {
|
||||
force_graphical
|
||||
} else if let Some(info) = supports_color::on(Stream::Stderr) {
|
||||
info.has_basic
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Detects known terminal apps based on env variables and returns true if
|
||||
// they support rendering links.
|
||||
pub(crate) fn use_links(&self) -> bool {
|
||||
if let Some(linkify) = self.linkify {
|
||||
linkify
|
||||
} else {
|
||||
supports_hyperlinks::on(Stream::Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_width(&self) -> usize {
|
||||
self.width
|
||||
.unwrap_or_else(|| term_size::dimensions().unwrap_or((80, 0)).0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A [ReportHandler] that displays a given [crate::Report] 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_hook] for more details on customizing your global printer.
|
||||
*/
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct MietteHandler {
|
||||
inner: Box<dyn ReportHandler + Send + Sync>,
|
||||
}
|
||||
|
||||
impl MietteHandler {
|
||||
/// Creates a new [MietteHandler] with default settings.
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MietteHandler {
|
||||
fn default() -> Self {
|
||||
MietteHandlerOpts::new().build()
|
||||
}
|
||||
}
|
||||
|
||||
impl ReportHandler for MietteHandler {
|
||||
fn debug(
|
||||
&self,
|
||||
diagnostic: &(dyn Diagnostic + 'static),
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
if f.alternate() {
|
||||
return fmt::Debug::fmt(diagnostic, f);
|
||||
}
|
||||
|
||||
self.inner.debug(diagnostic, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -46,9 +46,9 @@ impl GraphicalReportHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/// Disables error code linkification using [Diagnostic::url].
|
||||
pub fn without_code_linking(mut self) -> Self {
|
||||
self.linkify_code = false;
|
||||
/// Whether to enable error code linkification using [Diagnostic::url].
|
||||
pub fn with_links(mut self, links: bool) -> Self {
|
||||
self.linkify_code = links;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ impl GraphicalReportHandler {
|
|||
} else {
|
||||
self.theme.characters.ltop
|
||||
},
|
||||
self.theme.characters.hbar.to_string().repeat(1),
|
||||
self.theme.characters.hbar,
|
||||
)?;
|
||||
if let Some(source_name) = snippet.source.name() {
|
||||
let source_name = source_name.style(self.theme.styles.filename);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ pub use miette_derive::*;
|
|||
|
||||
pub use error::*;
|
||||
pub use eyreish::*;
|
||||
pub use handler::*;
|
||||
pub use handlers::*;
|
||||
pub use named_source::*;
|
||||
pub use protocol::*;
|
||||
|
|
@ -13,6 +14,7 @@ pub use protocol::*;
|
|||
mod chain;
|
||||
mod error;
|
||||
mod eyreish;
|
||||
mod handler;
|
||||
mod handlers;
|
||||
mod named_source;
|
||||
mod protocol;
|
||||
|
|
|
|||
|
|
@ -596,7 +596,7 @@ fn disable_url_links() -> Result<(), MietteError> {
|
|||
let err = MyBad;
|
||||
let mut out = String::new();
|
||||
GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
|
||||
.without_code_linking()
|
||||
.with_links(false)
|
||||
.render_report(&mut out, &err)
|
||||
.unwrap();
|
||||
println!("{}", out);
|
||||
|
|
|
|||
Loading…
Reference in New Issue