From ad2f85cd16748727d5079b77b8b8a9c1769343c9 Mon Sep 17 00:00:00 2001 From: Sergey Kasmy Date: Tue, 28 Feb 2023 20:07:30 +0100 Subject: [PATCH] Add HelpInfo::Report and Section::{report, with_report} functions This way you can attach reports to the error and not just types that implement std::error::Error --- src/handler.rs | 30 +++++++++++---------------- src/section/help.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ src/section/mod.rs | 7 +++++++ 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index ab7fdc4..e959eac 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -80,19 +80,12 @@ impl eyre::EyreHandler for Handler { )?; } - for section in self - .sections - .iter() - .filter(|s| matches!(s, HelpInfo::Error(_, _))) - { - write!(separated.ready(), "{}", section)?; - } - - for section in self - .sections - .iter() - .filter(|s| matches!(s, HelpInfo::Custom(_))) - { + for section in self.sections.iter().filter(|s| { + matches!( + s, + HelpInfo::Error(_, _) | HelpInfo::Report(_, _) | HelpInfo::Custom(_) + ) + }) { write!(separated.ready(), "{}", section)?; } @@ -130,11 +123,12 @@ impl eyre::EyreHandler for Handler { let mut h = f.header("\n"); let mut f = h.in_progress(); - for section in self - .sections - .iter() - .filter(|s| !matches!(s, HelpInfo::Custom(_) | HelpInfo::Error(_, _))) - { + for section in self.sections.iter().filter(|s| { + !matches!( + s, + HelpInfo::Custom(_) | HelpInfo::Error(_, _) | HelpInfo::Report(_, _) + ) + }) { write!(&mut f, "{}", section)?; f = h.ready(); } diff --git a/src/section/help.rs b/src/section/help.rs index a03cf3e..53c56f8 100644 --- a/src/section/help.rs +++ b/src/section/help.rs @@ -143,6 +143,29 @@ impl Section for Report { self } + fn report(mut self, report: Report) -> Self::Return { + if let Some(handler) = self.handler_mut().downcast_mut::() { + handler + .sections + .push(HelpInfo::Report(report, handler.theme)); + } + + self + } + + fn with_report(mut self, report: F) -> Self::Return + where + F: FnOnce() -> Report, + { + if let Some(handler) = self.handler_mut().downcast_mut::() { + handler + .sections + .push(HelpInfo::Report(report(), handler.theme)); + } + + self + } + fn suppress_backtrace(mut self, suppress: bool) -> Self::Return { if let Some(handler) = self.handler_mut().downcast_mut::() { handler.suppress_backtrace = suppress; @@ -243,6 +266,19 @@ where .map_err(|report| report.error(error())) } + fn report(self, report: Report) -> Self::Return { + self.map_err(|error| error.into()) + .map_err(|full_report| full_report.report(report)) + } + + fn with_report(self, report: F) -> Self::Return + where + F: FnOnce() -> Report, + { + self.map_err(|error| error.into()) + .map_err(|full_report| full_report.report(report())) + } + fn suppress_backtrace(self, suppress: bool) -> Self::Return { self.map_err(|error| error.into()) .map_err(|report| report.suppress_backtrace(suppress)) @@ -251,6 +287,7 @@ where pub(crate) enum HelpInfo { Error(Box, Theme), + Report(Report, Theme), Custom(Box), Note(Box, Theme), Warning(Box, Theme), @@ -289,6 +326,17 @@ impl Display for HelpInfo { write!(indented(f).ind(n), "{}", error.style(theme.help_info_error))?; } + Ok(()) + } + HelpInfo::Report(report, theme) => { + let errors = report.chain(); + + write!(f, "Error:")?; + for (n, error) in errors.enumerate() { + writeln!(f)?; + write!(indented(f).ind(n), "{}", error.style(theme.help_info_error))?; + } + Ok(()) } } @@ -315,6 +363,7 @@ impl fmt::Debug for HelpInfo { .field(&format_args!("{}", custom)) .finish(), HelpInfo::Error(error, ..) => f.debug_tuple("Error").field(error).finish(), + HelpInfo::Report(report, ..) => f.debug_tuple("Report").field(report).finish(), } } } diff --git a/src/section/mod.rs b/src/section/mod.rs index 4455890..8ed6b8b 100644 --- a/src/section/mod.rs +++ b/src/section/mod.rs @@ -1,4 +1,5 @@ //! Helpers for adding custom sections to error reports +use crate::eyre::Report; use crate::writers::WriterExt; use std::fmt::{self, Display}; @@ -230,6 +231,12 @@ pub trait Section: crate::private::Sealed { F: FnOnce() -> E, E: std::error::Error + Send + Sync + 'static; + fn report(self, report: Report) -> Self::Return; + + fn with_report(self, report: F) -> Self::Return + where + F: FnOnce() -> Report; + /// Add a Note to an error report, to be displayed after the chain of errors. /// /// # Examples