1use crate::{
3 config::Theme,
4 eyre::{Report, Result},
5 Section,
6};
7use indenter::indented;
8use owo_colors::OwoColorize;
9use std::fmt::Write;
10use std::fmt::{self, Display};
11
12impl Section for Report {
13 type Return = Report;
14
15 fn note<D>(mut self, note: D) -> Self::Return
16 where
17 D: Display + Send + Sync + 'static,
18 {
19 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
20 handler
21 .sections
22 .push(HelpInfo::Note(Box::new(note), handler.theme));
23 }
24
25 self
26 }
27
28 fn with_note<D, F>(mut self, note: F) -> Self::Return
29 where
30 D: Display + Send + Sync + 'static,
31 F: FnOnce() -> D,
32 {
33 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
34 handler
35 .sections
36 .push(HelpInfo::Note(Box::new(note()), handler.theme));
37 }
38
39 self
40 }
41
42 fn warning<D>(mut self, warning: D) -> Self::Return
43 where
44 D: Display + Send + Sync + 'static,
45 {
46 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
47 handler
48 .sections
49 .push(HelpInfo::Warning(Box::new(warning), handler.theme));
50 }
51
52 self
53 }
54
55 fn with_warning<D, F>(mut self, warning: F) -> Self::Return
56 where
57 D: Display + Send + Sync + 'static,
58 F: FnOnce() -> D,
59 {
60 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
61 handler
62 .sections
63 .push(HelpInfo::Warning(Box::new(warning()), handler.theme));
64 }
65
66 self
67 }
68
69 fn suggestion<D>(mut self, suggestion: D) -> Self::Return
70 where
71 D: Display + Send + Sync + 'static,
72 {
73 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
74 handler
75 .sections
76 .push(HelpInfo::Suggestion(Box::new(suggestion), handler.theme));
77 }
78
79 self
80 }
81
82 fn with_suggestion<D, F>(mut self, suggestion: F) -> Self::Return
83 where
84 D: Display + Send + Sync + 'static,
85 F: FnOnce() -> D,
86 {
87 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
88 handler
89 .sections
90 .push(HelpInfo::Suggestion(Box::new(suggestion()), handler.theme));
91 }
92
93 self
94 }
95
96 fn with_section<D, F>(mut self, section: F) -> Self::Return
97 where
98 D: Display + Send + Sync + 'static,
99 F: FnOnce() -> D,
100 {
101 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
102 let section = Box::new(section());
103 handler.sections.push(HelpInfo::Custom(section));
104 }
105
106 self
107 }
108
109 fn section<D>(mut self, section: D) -> Self::Return
110 where
111 D: Display + Send + Sync + 'static,
112 {
113 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
114 let section = Box::new(section);
115 handler.sections.push(HelpInfo::Custom(section));
116 }
117
118 self
119 }
120
121 fn error<E2>(mut self, error: E2) -> Self::Return
122 where
123 E2: std::error::Error + Send + Sync + 'static,
124 {
125 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
126 let error = error.into();
127 handler.sections.push(HelpInfo::Error(error, handler.theme));
128 }
129
130 self
131 }
132
133 fn with_error<E2, F>(mut self, error: F) -> Self::Return
134 where
135 F: FnOnce() -> E2,
136 E2: std::error::Error + Send + Sync + 'static,
137 {
138 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
139 let error = error().into();
140 handler.sections.push(HelpInfo::Error(error, handler.theme));
141 }
142
143 self
144 }
145
146 fn suppress_backtrace(mut self, suppress: bool) -> Self::Return {
147 if let Some(handler) = self.handler_mut().downcast_mut::<crate::Handler>() {
148 handler.suppress_backtrace = suppress;
149 }
150
151 self
152 }
153}
154
155impl<T, E> Section for Result<T, E>
156where
157 E: Into<Report>,
158{
159 type Return = Result<T, Report>;
160
161 fn note<D>(self, note: D) -> Self::Return
162 where
163 D: Display + Send + Sync + 'static,
164 {
165 self.map_err(|error| error.into())
166 .map_err(|report| report.note(note))
167 }
168
169 fn with_note<D, F>(self, note: F) -> Self::Return
170 where
171 D: Display + Send + Sync + 'static,
172 F: FnOnce() -> D,
173 {
174 self.map_err(|error| error.into())
175 .map_err(|report| report.note(note()))
176 }
177
178 fn warning<D>(self, warning: D) -> Self::Return
179 where
180 D: Display + Send + Sync + 'static,
181 {
182 self.map_err(|error| error.into())
183 .map_err(|report| report.warning(warning))
184 }
185
186 fn with_warning<D, F>(self, warning: F) -> Self::Return
187 where
188 D: Display + Send + Sync + 'static,
189 F: FnOnce() -> D,
190 {
191 self.map_err(|error| error.into())
192 .map_err(|report| report.warning(warning()))
193 }
194
195 fn suggestion<D>(self, suggestion: D) -> Self::Return
196 where
197 D: Display + Send + Sync + 'static,
198 {
199 self.map_err(|error| error.into())
200 .map_err(|report| report.suggestion(suggestion))
201 }
202
203 fn with_suggestion<D, F>(self, suggestion: F) -> Self::Return
204 where
205 D: Display + Send + Sync + 'static,
206 F: FnOnce() -> D,
207 {
208 self.map_err(|error| error.into())
209 .map_err(|report| report.suggestion(suggestion()))
210 }
211
212 fn with_section<D, F>(self, section: F) -> Self::Return
213 where
214 D: Display + Send + Sync + 'static,
215 F: FnOnce() -> D,
216 {
217 self.map_err(|error| error.into())
218 .map_err(|report| report.section(section()))
219 }
220
221 fn section<D>(self, section: D) -> Self::Return
222 where
223 D: Display + Send + Sync + 'static,
224 {
225 self.map_err(|error| error.into())
226 .map_err(|report| report.section(section))
227 }
228
229 fn error<E2>(self, error: E2) -> Self::Return
230 where
231 E2: std::error::Error + Send + Sync + 'static,
232 {
233 self.map_err(|error| error.into())
234 .map_err(|report| report.error(error))
235 }
236
237 fn with_error<E2, F>(self, error: F) -> Self::Return
238 where
239 F: FnOnce() -> E2,
240 E2: std::error::Error + Send + Sync + 'static,
241 {
242 self.map_err(|error| error.into())
243 .map_err(|report| report.error(error()))
244 }
245
246 fn suppress_backtrace(self, suppress: bool) -> Self::Return {
247 self.map_err(|error| error.into())
248 .map_err(|report| report.suppress_backtrace(suppress))
249 }
250}
251
252pub(crate) enum HelpInfo {
253 Error(Box<dyn std::error::Error + Send + Sync + 'static>, Theme),
254 Custom(Box<dyn Display + Send + Sync + 'static>),
255 Note(Box<dyn Display + Send + Sync + 'static>, Theme),
256 Warning(Box<dyn Display + Send + Sync + 'static>, Theme),
257 Suggestion(Box<dyn Display + Send + Sync + 'static>, Theme),
258}
259
260impl Display for HelpInfo {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 match self {
263 HelpInfo::Note(note, theme) => {
264 write!(f, "{}: {}", "Note".style(theme.help_info_note), note)
265 }
266 HelpInfo::Warning(warning, theme) => write!(
267 f,
268 "{}: {}",
269 "Warning".style(theme.help_info_warning),
270 warning
271 ),
272 HelpInfo::Suggestion(suggestion, theme) => write!(
273 f,
274 "{}: {}",
275 "Suggestion".style(theme.help_info_suggestion),
276 suggestion
277 ),
278 HelpInfo::Custom(section) => write!(f, "{}", section),
279 HelpInfo::Error(error, theme) => {
280 let errors = std::iter::successors(
282 Some(error.as_ref() as &(dyn std::error::Error + 'static)),
283 |e| e.source(),
284 );
285
286 write!(f, "Error:")?;
287 for (n, error) in errors.enumerate() {
288 writeln!(f)?;
289 write!(indented(f).ind(n), "{}", error.style(theme.help_info_error))?;
290 }
291
292 Ok(())
293 }
294 }
295 }
296}
297
298impl fmt::Debug for HelpInfo {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 match self {
301 HelpInfo::Note(note, ..) => f
302 .debug_tuple("Note")
303 .field(&format_args!("{}", note))
304 .finish(),
305 HelpInfo::Warning(warning, ..) => f
306 .debug_tuple("Warning")
307 .field(&format_args!("{}", warning))
308 .finish(),
309 HelpInfo::Suggestion(suggestion, ..) => f
310 .debug_tuple("Suggestion")
311 .field(&format_args!("{}", suggestion))
312 .finish(),
313 HelpInfo::Custom(custom, ..) => f
314 .debug_tuple("CustomSection")
315 .field(&format_args!("{}", custom))
316 .finish(),
317 HelpInfo::Error(error, ..) => f.debug_tuple("Error").field(error).finish(),
318 }
319 }
320}