1use std::fmt::{Display, Formatter, Result};
2
3pub struct PrettyPrintError<'a>(pub &'a anyhow::Error);
6
7impl Display for PrettyPrintError<'_> {
8 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
9 let mut i = 0;
10 let mut has_details = false;
11
12 let descriptions = self
13 .0
14 .chain()
15 .map(|cause| cause.to_string())
16 .collect::<Vec<_>>();
17
18 for description in &descriptions {
19 let hidden = description.starts_with("Execution of ");
21 if !hidden {
22 let header =
23 description
24 .split_once('\n')
25 .map_or(description.as_str(), |(header, _)| {
26 has_details = true;
27 header
28 });
29 match i {
30 0 => write!(f, "{header}")?,
31 1 => write!(f, "\n\nCaused by:\n- {header}")?,
32 _ => write!(f, "\n- {header}")?,
33 }
34 i += 1;
35 } else {
36 has_details = true;
37 }
38 }
39 if has_details {
40 write!(f, "\n\nDebug info:")?;
41 for description in descriptions {
42 f.write_str("\n")?;
43 WithDash(&description).fmt(f)?;
44 }
45 }
46 Ok(())
47 }
48}
49
50struct WithDash<'a>(&'a str);
52
53impl Display for WithDash<'_> {
54 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
55 let mut lines = self.0.lines();
56 if let Some(line) = lines.next() {
57 write!(f, "- {line}")?;
58 }
59 for line in lines {
60 write!(f, "\n {line}")?;
61 }
62 Ok(())
63 }
64}