use crate::{Report, Result};
use ansi_term::Color::*;
use std::fmt::{self, Display};
pub trait Help<T>: private::Sealed {
fn note<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn with_note<C, F>(self, f: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C;
fn warning<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn with_warning<C, F>(self, f: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C;
fn suggestion<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn with_suggestion<C, F>(self, f: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C;
}
impl<T, E> Help<T> for std::result::Result<T, E>
where
E: Into<Report>,
{
fn note<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut().help.push(HelpInfo::Note(Box::new(context)));
e
})
}
fn with_note<C, F>(self, context: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut()
.help
.push(HelpInfo::Note(Box::new(context())));
e
})
}
fn warning<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut()
.help
.push(HelpInfo::Warning(Box::new(context)));
e
})
}
fn with_warning<C, F>(self, context: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut()
.help
.push(HelpInfo::Warning(Box::new(context())));
e
})
}
fn suggestion<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut()
.help
.push(HelpInfo::Suggestion(Box::new(context)));
e
})
}
fn with_suggestion<C, F>(self, context: F) -> Result<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|e| {
let mut e = e.into();
e.context_mut()
.help
.push(HelpInfo::Suggestion(Box::new(context())));
e
})
}
}
pub(crate) enum HelpInfo {
Note(Box<dyn Display + Send + Sync + 'static>),
Warning(Box<dyn Display + Send + Sync + 'static>),
Suggestion(Box<dyn Display + Send + Sync + 'static>),
}
impl Display for HelpInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Note(context) => write!(f, "{}: {}", Cyan.paint("Note"), context),
Self::Warning(context) => write!(f, "{}: {}", Yellow.paint("Warning"), context),
Self::Suggestion(context) => write!(f, "{}: {}", Cyan.paint("Suggestion"), context),
}
}
}
impl fmt::Debug for HelpInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Note(context) => f
.debug_tuple("Note")
.field(&format_args!("{}", context))
.finish(),
Self::Warning(context) => f
.debug_tuple("Warning")
.field(&format_args!("{}", context))
.finish(),
Self::Suggestion(context) => f
.debug_tuple("Suggestion")
.field(&format_args!("{}", context))
.finish(),
}
}
}
pub(crate) mod private {
use crate::Report;
pub trait Sealed {}
impl<T, E> Sealed for std::result::Result<T, E> where E: Into<Report> {}
}