1use eyre::EyreHandler;
2use std::{error::Error, fmt};
3
4#[derive(Default)]
6pub struct Handler {
7 debug_handler: Option<Box<dyn EyreHandler>>,
8}
9
10impl Handler {
11 pub fn new() -> Self {
13 Self::default()
14 }
15
16 pub fn debug_handler(mut self, debug_handler: Option<Box<dyn EyreHandler>>) -> Self {
18 self.debug_handler = debug_handler;
19 self
20 }
21}
22
23impl EyreHandler for Handler {
24 fn display(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 f.write_str(&foundry_common::errors::display_chain(error))
26 }
27
28 fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 if let Some(debug_handler) = &self.debug_handler {
30 return debug_handler.debug(error, f);
31 }
32
33 if f.alternate() {
34 return fmt::Debug::fmt(error, f);
35 }
36 let errors = foundry_common::errors::dedup_chain(error);
37
38 let (error, sources) = errors.split_first().unwrap();
39 write!(f, "{error}")?;
40
41 if !sources.is_empty() {
42 write!(f, "\n\nContext:")?;
43
44 let multiple = sources.len() > 1;
45 for (n, error) in sources.iter().enumerate() {
46 writeln!(f)?;
47 if multiple {
48 write!(f, "- Error #{n}: {error}")?;
49 } else {
50 write!(f, "- {error}")?;
51 }
52 }
53 }
54
55 Ok(())
56 }
57
58 fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {
59 if let Some(debug_handler) = &mut self.debug_handler {
60 debug_handler.track_caller(location);
61 }
62 }
63}
64
65pub fn install() {
75 if std::env::var_os("RUST_BACKTRACE").is_none() {
76 unsafe {
77 std::env::set_var("RUST_BACKTRACE", "1");
78 }
79 }
80
81 let panic_section =
82 "This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry";
83 let (panic_hook, debug_hook) =
84 color_eyre::config::HookBuilder::default().panic_section(panic_section).into_hooks();
85 panic_hook.install();
86 let debug_hook = debug_hook.into_eyre_hook();
87 let debug = std::env::var_os("FOUNDRY_DEBUG").is_some();
88 if let Err(e) = eyre::set_hook(Box::new(move |e| {
89 Box::new(Handler::new().debug_handler(debug.then(|| debug_hook(e))))
90 })) {
91 debug!("failed to install eyre error hook: {e}");
92 }
93}