use cabin_core::ColorChoice;
use termcolor::{StandardStream, WriteColor};
use crate::diagnostic_registry::{DiagnosticCandidate, downcast_diagnostic};
pub(crate) fn render_error(error: &anyhow::Error, color: ColorChoice) {
let mut current: Option<&(dyn std::error::Error + 'static)> = Some(error.as_ref());
let mut deepest: Option<DiagnosticCandidate<'_>> = None;
while let Some(err) = current {
if let Some(diag) = downcast_diagnostic(err) {
deepest = Some(diag);
}
current = err.source();
}
let mut stderr = StandardStream::stderr(cabin_diagnostics::termcolor_choice(color));
if let Some(candidate) = deepest {
let _ = candidate.render(error, &mut stderr, color);
return;
}
let _ = write_plain_error(&mut stderr, &format!("{error:#}"));
}
pub(crate) fn write_plain_error(stderr: &mut StandardStream, message: &str) -> std::io::Result<()> {
use std::io::Write as _;
if stderr.supports_color() {
let mut spec = termcolor::ColorSpec::new();
spec.set_fg(Some(termcolor::Color::Red)).set_bold(true);
stderr.set_color(&spec)?;
stderr.write_all(b"error")?;
stderr.reset()?;
writeln!(stderr, ": {message}")
} else {
writeln!(stderr, "error: {message}")
}
}