From b9ea587159464c0090d9510567e5ea93bb772b49 Mon Sep 17 00:00:00 2001 From: Luca Palmieri Date: Wed, 10 Aug 2022 01:32:02 +0100 Subject: [PATCH] feat(graphical): Allow miette users to opt-out of the rendering of the cause chain (#192) Fixes: https://github.com/zkat/miette/issues/191 --- src/handler.rs | 27 +++++++++++++++++++++++++++ src/handlers/graphical.rs | 21 +++++++++++++++++++++ src/handlers/narratable.rs | 19 ++++++++++++++++++- src/lib.rs | 17 ++++++++--------- 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index a6e20da..b5f9993 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -56,6 +56,7 @@ pub struct MietteHandlerOpts { pub(crate) footer: Option, pub(crate) context_lines: Option, pub(crate) tab_width: Option, + pub(crate) with_cause_chain: Option, } impl MietteHandlerOpts { @@ -87,6 +88,18 @@ impl MietteHandlerOpts { self } + /// Include the cause chain of the top-level error in the report. + pub fn with_cause_chain(mut self) -> Self { + self.with_cause_chain = Some(true); + self + } + + /// Do not include the cause chain of the top-level error in the report. + pub fn without_cause_chain(mut self) -> Self { + self.with_cause_chain = Some(false); + self + } + /// If true, colors will be used during graphical rendering, regardless /// of whether or not the terminal supports them. /// @@ -165,6 +178,13 @@ impl MietteHandlerOpts { if let Some(context_lines) = self.context_lines { handler = handler.with_context_lines(context_lines); } + if let Some(with_cause_chain) = self.with_cause_chain { + if with_cause_chain { + handler = handler.with_cause_chain(); + } else { + handler = handler.without_cause_chain(); + } + } MietteHandler { inner: Box::new(handler), } @@ -197,6 +217,13 @@ impl MietteHandlerOpts { .with_width(width) .with_links(linkify) .with_theme(theme); + if let Some(with_cause_chain) = self.with_cause_chain { + if with_cause_chain { + handler = handler.with_cause_chain(); + } else { + handler = handler.without_cause_chain(); + } + } if let Some(footer) = self.footer { handler = handler.with_footer(footer); } diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs index 765a1d2..0034a8b 100644 --- a/src/handlers/graphical.rs +++ b/src/handlers/graphical.rs @@ -28,6 +28,7 @@ pub struct GraphicalReportHandler { pub(crate) footer: Option, pub(crate) context_lines: usize, pub(crate) tab_width: Option, + pub(crate) with_cause_chain: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -48,6 +49,7 @@ impl GraphicalReportHandler { footer: None, context_lines: 1, tab_width: None, + with_cause_chain: true, } } @@ -60,6 +62,7 @@ impl GraphicalReportHandler { footer: None, context_lines: 1, tab_width: None, + with_cause_chain: true, } } @@ -79,6 +82,20 @@ impl GraphicalReportHandler { self } + /// Include the cause chain of the top-level error in the graphical output, + /// if available. + pub fn with_cause_chain(mut self) -> Self { + self.with_cause_chain = true; + self + } + + /// Do not include the cause chain of the top-level error in the graphical + /// output. + pub fn without_cause_chain(mut self) -> Self { + self.with_cause_chain = false; + self + } + /// Whether to include [`Diagnostic::url()`] in the output. /// /// Disabling this is not recommended, but can be useful for more easily @@ -199,6 +216,10 @@ impl GraphicalReportHandler { writeln!(f, "{}", textwrap::fill(&diagnostic.to_string(), opts))?; + if !self.with_cause_chain { + return Ok(()); + } + if let Some(mut cause_iter) = diagnostic .diagnostic_source() .map(DiagnosticChain::from_diagnostic) diff --git a/src/handlers/narratable.rs b/src/handlers/narratable.rs index 5ff3ae9..5855752 100644 --- a/src/handlers/narratable.rs +++ b/src/handlers/narratable.rs @@ -14,6 +14,7 @@ non-graphical environments, such as non-TTY output. #[derive(Debug, Clone)] pub struct NarratableReportHandler { context_lines: usize, + with_cause_chain: bool, footer: Option, } @@ -24,9 +25,23 @@ impl NarratableReportHandler { Self { footer: None, context_lines: 1, + with_cause_chain: true, } } + /// Include the cause chain of the top-level error in the report, if + /// available. + pub fn with_cause_chain(mut self) -> Self { + self.with_cause_chain = true; + self + } + + /// Do not include the cause chain of the top-level error in the report. + pub fn without_cause_chain(mut self) -> Self { + self.with_cause_chain = false; + self + } + /// Set the footer to be displayed at the end of the report. pub fn with_footer(mut self, footer: String) -> Self { self.footer = Some(footer); @@ -57,7 +72,9 @@ impl NarratableReportHandler { diagnostic: &(dyn Diagnostic), ) -> fmt::Result { self.render_header(f, diagnostic)?; - self.render_causes(f, diagnostic)?; + if self.with_cause_chain { + self.render_causes(f, diagnostic)?; + } let src = diagnostic.source_code(); self.render_snippets(f, diagnostic, src)?; self.render_footer(f, diagnostic)?; diff --git a/src/lib.rs b/src/lib.rs index 27875fc..de09898 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -582,15 +582,14 @@ //! `miette` was not developed in a void. It owes enormous credit to various //! other projects and their authors: //! -//! - [`anyhow`](http://crates.io/crates/anyhow) and -//! [`color-eyre`](https://crates.io/crates/color-eyre): these two -//! enormously influential error handling libraries have pushed forward the -//! experience of application-level error handling and error reporting. -//! `miette`'s `Report` type is an attempt at a very very rough version of -//! their `Report` types. -//! - [`thiserror`](https://crates.io/crates/thiserror) for setting the -//! standard for library-level error definitions, and for being the -//! inspiration behind `miette`'s derive macro. +//! - [`anyhow`](http://crates.io/crates/anyhow) and [`color-eyre`](https://crates.io/crates/color-eyre): +//! these two enormously influential error handling libraries have pushed +//! forward the experience of application-level error handling and error +//! reporting. `miette`'s `Report` type is an attempt at a very very rough +//! version of their `Report` types. +//! - [`thiserror`](https://crates.io/crates/thiserror) for setting the standard +//! for library-level error definitions, and for being the inspiration behind +//! `miette`'s derive macro. //! - `rustc` and [@estebank](https://github.com/estebank) for their //! state-of-the-art work in compiler diagnostics. //! - [`ariadne`](https://crates.io/crates/ariadne) for pushing forward how