simple_eyre/
lib.rs

1//! This library provides a custom [`eyre::EyreHandler`] type for usage with [`eyre`] that provides
2//! a minimal error report with no additional context. Essentially the minimal implementation of an
3//! error reporter.
4//!
5//! ## Setup
6//!
7//! Add the following to your toml file:
8//!
9//! ```toml
10//! [dependencies]
11//! simple-eyre = "0.3"
12//! ```
13//!
14//! Then install the hook handler before constructing any `eyre::Report` types.
15//!
16//! # Example
17//!
18//! ```rust,should_panic
19//! use simple_eyre::eyre::{eyre, WrapErr, Report};
20//!
21//! fn main() -> Result<(), Report> {
22//!     simple_eyre::install()?;
23//!
24//!     let e: Report = eyre!("oh no this program is just bad!");
25//!
26//!     Err(e).wrap_err("usage example successfully experienced a failure")
27//! }
28//! ```
29//!
30//! [`eyre::EyreHandler`]: https://docs.rs/eyre/*/eyre/trait.EyreHandler.html
31//! [`eyre`]: https://docs.rs/eyre
32#![doc(html_root_url = "https://docs.rs/simple-eyre/0.3.1")]
33#![warn(
34    missing_debug_implementations,
35    missing_docs,
36    missing_doc_code_examples,
37    rust_2018_idioms,
38    unreachable_pub,
39    bad_style,
40    const_err,
41    dead_code,
42    improper_ctypes,
43    non_shorthand_field_patterns,
44    no_mangle_generic_items,
45    overflowing_literals,
46    path_statements,
47    patterns_in_fns_without_body,
48    private_in_public,
49    unconditional_recursion,
50    unused,
51    unused_allocation,
52    unused_comparisons,
53    unused_parens,
54    while_true
55)]
56pub use eyre;
57#[doc(hidden)]
58pub use eyre::{Report, Result};
59
60use eyre::EyreHandler;
61use indenter::indented;
62use std::error::Error;
63
64/// A custom context type for minimal error reporting via `eyre`
65#[derive(Debug)]
66pub struct Handler;
67
68impl EyreHandler for Handler {
69    fn debug(
70        &self,
71        error: &(dyn Error + 'static),
72        f: &mut core::fmt::Formatter<'_>,
73    ) -> core::fmt::Result {
74        use core::fmt::Write as _;
75
76        if f.alternate() {
77            return core::fmt::Debug::fmt(error, f);
78        }
79
80        write!(f, "{}", error)?;
81
82        if let Some(cause) = error.source() {
83            write!(f, "\n\nCaused by:")?;
84
85            let multiple = cause.source().is_some();
86            let errors = std::iter::successors(Some(cause), |e| (*e).source());
87
88            for (n, error) in errors.enumerate() {
89                writeln!(f)?;
90
91                if multiple {
92                    write!(indented(f).ind(n), "{}", error)?;
93                } else {
94                    write!(indented(f), "{}", error)?;
95                }
96            }
97        }
98
99        Ok(())
100    }
101}
102
103/// Install the `simple-eyre` hook as the global error report hook.
104///
105/// # Details
106///
107/// This function must be called to enable the customization of `eyre::Report`
108/// provided by `simple-eyre`. This function should be called early, ideally
109/// before any errors could be encountered.
110///
111/// Only the first install will succeed. Calling this function after another
112/// report handler has been installed will cause an error. **Note**: This
113/// function _must_ be called before any `eyre::Report`s are constructed to
114/// prevent the default handler from being installed.
115pub fn install() -> Result<()> {
116    crate::eyre::set_hook(Box::new(move |_| Box::new(Handler)))?;
117
118    Ok(())
119}