diff --git a/src/lib.rs b/src/lib.rs index 3e3504a7..28abd23c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ pub use eyreish::*; pub use handler::*; pub use handlers::*; pub use named_source::*; +pub use panic::*; pub use protocol::*; mod chain; @@ -19,5 +20,6 @@ mod eyreish; mod handler; mod handlers; mod named_source; +mod panic; mod protocol; mod source_impls; diff --git a/src/panic.rs b/src/panic.rs new file mode 100644 index 00000000..a66b81f8 --- /dev/null +++ b/src/panic.rs @@ -0,0 +1,30 @@ +use thiserror::Error; + +use crate::{self as miette, Context, Diagnostic, Result}; + +/// Tells miette to render panics using its rendering engine. +pub fn set_panic_hook() { + std::panic::set_hook(Box::new(|info| { + let mut message = "Something went wrong".to_string(); + let payload = info.payload(); + if let Some(msg) = payload.downcast_ref::<&str>() { + message = msg.to_string(); + } + if let Some(msg) = payload.downcast_ref::() { + message = msg.clone(); + } + let mut report: Result<()> = Err(Panic(message).into()); + if let Some(loc) = info.location() { + report = report + .with_context(|| format!("at {}:{}:{}", loc.file(), loc.line(), loc.column())); + } + if let Err(err) = report.with_context(|| "Main thread panicked.".to_string()) { + eprintln!("Error: {:?}", err); + } + })); +} + +#[derive(Debug, Error, Diagnostic)] +#[error("{0}")] +#[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))] +struct Panic(String);