diff --git a/src/bin/tectonic.rs b/src/bin/tectonic.rs index 7d5901141..6d4a7b366 100644 --- a/src/bin/tectonic.rs +++ b/src/bin/tectonic.rs @@ -261,12 +261,12 @@ fn main() { "this is a BETA release; ask questions and report bugs at https://tectonic.newton.cx/" ); - // Now that we've got colorized output, we're to pass off to the inner - // function ... all so that we can print out the word "error:" in red. - // This code parallels various bits of the `error_chain` crate. + // Now that we've got colorized output, pass off to the inner function ... + // all so that we can print out the word "error:" in red. This code + // parallels various bits of the `error_chain` crate. if let Err(ref e) = inner(args, config, &mut *status) { - tt_error!(status, ""; e); + status.report_error(e); process::exit(1) } } diff --git a/src/status/mod.rs b/src/status/mod.rs index 663dc9f02..29b18b89c 100644 --- a/src/status/mod.rs +++ b/src/status/mod.rs @@ -63,8 +63,25 @@ pub enum MessageKind { pub trait StatusBackend { /// Report a message to the status backend. + /// + /// If `err` is not None, it represents an error that somehow caused the + /// current message to be reported. It should be displayed in some + /// appropriate fashion. fn report(&mut self, kind: MessageKind, args: Arguments, err: Option<&Error>); + /// Report an error to the status backend. + /// + /// Unlike the basic `report` function, in this case there is no additional + /// contextual information provided. The default implementation delegates to + /// `report()` with a generic lead-in message of "an error occurred". + fn report_error(&mut self, err: &Error) { + self.report( + MessageKind::Error, + format_args!("an error occurred"), + Some(err), + ) + } + /// Issue a note-level status, idealy highlighting a particular phrase. /// /// This is a bit of a hack. For [`driver::ProcessingSession::run`], I diff --git a/src/status/plain.rs b/src/status/plain.rs index af5090b88..ea80abb05 100644 --- a/src/status/plain.rs +++ b/src/status/plain.rs @@ -41,6 +41,20 @@ impl StatusBackend for PlainStatusBackend { } } + fn report_error(&mut self, err: &Error) { + let mut prefix = "error"; + + for item in err.iter() { + eprintln!("{}: {}", prefix, item); + prefix = "caused by"; + } + + if let Some(backtrace) = err.backtrace() { + eprintln!("debugging: backtrace follows:"); + eprintln!("{:?}", backtrace); + } + } + fn note_highlighted(&mut self, before: &str, highlighted: &str, after: &str) { if self.chatter > ChatterLevel::Minimal { self.report( diff --git a/src/status/termcolor.rs b/src/status/termcolor.rs index 7099a1c1b..38ea70c83 100644 --- a/src/status/termcolor.rs +++ b/src/status/termcolor.rs @@ -168,6 +168,27 @@ impl StatusBackend for TermcolorStatusBackend { } } + fn report_error(&mut self, err: &Error) { + let mut first = true; + let kind = MessageKind::Error; + + for item in err.iter() { + if first { + self.generic_message(kind, None, format_args!("{}", item)); + first = false; + } else { + self.generic_message(kind, Some("caused by:"), format_args!("{}", item)); + } + } + + if let Some(backtrace) = err.backtrace() { + self.generic_message(kind, Some("debugging:"), format_args!("backtrace follows:")); + self.with_stream(kind, |s| { + writeln!(s, "{:?}", backtrace).expect("backtrace dump failed"); + }); + } + } + fn note_highlighted(&mut self, before: &str, highlighted: &str, after: &str) { if self.chatter > ChatterLevel::Minimal { write!(self.stdout, "{}", before).expect("write to stdout failed");