use std::env;
use std::panic;
use std::thread;
use crate::consts::BACKTRACE;
use crate::consts::LIB_BACKTRACE;
use crate::Frame;
use crate::FrameFilter;
use crate::InstallError;
use crate::Theme;
use crate::Verbosity;
use crate::GLOBAL_SETTINGS;
pub(crate) struct Bundle<'a, T> {
pub config: &'a Config,
pub data: T,
}
#[must_use = "`Config` is useless unless used in panic hook or installed"]
pub struct Config {
pub(crate) filters: Vec<Box<FrameFilter>>,
pub(crate) theme: Theme,
pub(crate) error: Verbosity,
pub(crate) panic: Verbosity,
}
impl Config {
pub(crate) fn bundle<T>(&self, data: T) -> Bundle<'_, T> {
Bundle { config: self, data }
}
pub(crate) fn selected_verbosity(&self) -> Verbosity {
if thread::panicking() {
self.panic
} else {
self.error
}
}
#[inline]
pub fn blank() -> Self {
Self {
filters: Vec::new(),
theme: Theme::new(),
error: Verbosity::Minimal,
panic: Verbosity::Minimal,
}
}
#[inline]
pub fn new() -> Self {
Self {
filters: Frame::default_filters(),
error: Verbosity::error().unwrap_or_default(),
panic: Verbosity::panic().unwrap_or_default(),
theme: Theme::new(),
}
}
#[allow(clippy::missing_panics_doc)]
#[inline]
pub fn install(self) -> Result<&'static Self, InstallError> {
env::set_var(BACKTRACE, self.panic.env());
env::set_var(LIB_BACKTRACE, self.error.env());
let config = GLOBAL_SETTINGS
.set(self)
.map_err(|_| InstallError)
.map(|()| GLOBAL_SETTINGS.get().expect("`OnceLock` was just set"))?;
panic::set_hook(Box::new(config.panic_hook()));
#[cfg(feature = "eyre")]
eyre::set_hook(config.eyre_hook()).map_err(|_| InstallError)?;
Ok(config)
}
#[inline]
pub fn panic_verbosity(mut self, verbosity: Verbosity) -> Self {
self.panic = verbosity;
self
}
#[inline]
pub fn error_verbosity(mut self, verbosity: Verbosity) -> Self {
self.error = verbosity;
self
}
#[inline]
pub fn verbosity(mut self, verbosity: Verbosity) -> Self {
self.error = verbosity;
self.panic = verbosity;
self
}
#[inline]
pub fn theme(mut self, theme: Theme) -> Self {
self.theme = theme;
self
}
#[inline]
pub fn filter(mut self, filter: Box<FrameFilter>) -> Self {
self.filters.push(filter);
self
}
}
impl Default for Config {
#[inline]
fn default() -> Self {
Self::new()
}
}