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