feat(color-eyre): Add a default color-eyre feature

Apps can now enable color-eyre hooks using the with_color_eyre_hooks
method on CrosstermBackend. This is also added to the default features
in the Cargo.toml file, and the defaults that are applied to terminals
created using CrosstermBackend::into_terminal_with_defaults.
This commit is contained in:
Josh McKinney
2024-06-15 18:12:12 -07:00
parent 754d1b088a
commit 83ec0ae1cf
3 changed files with 50 additions and 27 deletions

View File

@@ -28,6 +28,7 @@ rust-version = "1.74.0"
bitflags = "2.3"
cassowary = "0.3"
compact_str = "0.7.1"
color-eyre = { version = "0.6.2", optional = true }
crossterm = { version = "0.27", optional = true }
document-features = { version = "0.2.7", optional = true }
itertools = "0.13"
@@ -49,7 +50,6 @@ unicode-width = "0.1.13"
anyhow = "1.0.71"
argh = "0.1.12"
better-panic = "0.3.0"
color-eyre = "0.6.2"
criterion = { version = "0.5.1", features = ["html_reports"] }
derive_builder = "0.20.0"
fakeit = "1.1"
@@ -106,7 +106,7 @@ use_self = "warn"
## By default, we enable the crossterm backend as this is a reasonable choice for most applications
## as it is supported on Linux/Mac/Windows systems. We also enable the `underline-color` feature
## which allows you to set the underline color of text.
default = ["crossterm", "underline-color"]
default = ["crossterm", "underline-color", "color-eyre"]
#! Generally an application will only use one backend, so you should only enable one of the following features:
## enables the [`CrosstermBackend`](backend::CrosstermBackend) backend and adds a dependency on [`crossterm`].
crossterm = ["dep:crossterm"]
@@ -116,6 +116,12 @@ termion = ["dep:termion"]
termwiz = ["dep:termwiz"]
#! The following optional features are available for all backends:
## enables the [`color-eyre`](color_eyre) crate which provides a better error handling experience.
## See [`CrosstermBackend::with_color_eyre_hooks`](crate::backend::CrosstermBackend::with_color_eyre_hooks)
## for more details.
color-eyre = ["dep:color-eyre"]
## enables serialization and deserialization of style and color types using the [`serde`] crate.
## This is useful if you want to save themes to a file.
serde = ["dep:serde", "bitflags/serde", "compact_str/serde"]

View File

@@ -26,13 +26,9 @@
// is useful when the state is only used by the widget and doesn't need to be shared with
// other widgets.
use std::{
io::stdout,
panic,
time::{Duration, Instant},
};
use std::time::{Duration, Instant};
use color_eyre::{config::HookBuilder, eyre, Result};
use color_eyre::Result;
use palette::{convert::FromColorUnclamped, Okhsv, Srgb};
use ratatui::{
backend::{Backend, CrosstermBackend},
@@ -258,21 +254,3 @@ impl ColorsWidget {
}
}
}
/// Install `color_eyre` panic and error hooks
///
/// The hooks restore the terminal to a usable state before printing the error message.
fn install_error_hooks() -> Result<()> {
let (panic, error) = HookBuilder::default().into_hooks();
let panic = panic.into_panic_hook();
let error = error.into_eyre_hook();
eyre::set_hook(Box::new(move |e| {
let _ = CrosstermBackend::reset(stdout());
error(e)
}))?;
panic::set_hook(Box::new(move |info| {
let _ = CrosstermBackend::reset(stdout());
panic(info);
}));
Ok(())
}

View File

@@ -204,6 +204,9 @@ impl CrosstermBackend<io::Stderr> {
///
/// Raw mode and alternate screen are restored when the `CrosstermBackend` is dropped.
///
/// If the `color-eyre` feature is enabled, the color-eyre panic and error report hooks are
/// installed.
///
/// # Example
///
/// ```rust,no_run
@@ -213,7 +216,10 @@ impl CrosstermBackend<io::Stderr> {
/// # std::io::Result::Ok(())
/// ```
pub fn stderr_with_defaults() -> io::Result<Self> {
Self::stderr().with_raw_mode()?.with_alternate_screen()
let backend = Self::stderr().with_raw_mode()?.with_alternate_screen()?;
#[cfg(feature = "color-eyre")]
let backend = backend.with_color_eyre_hooks()?;
Ok(backend)
}
}
@@ -335,6 +341,39 @@ impl<W: Write> CrosstermBackend<W> {
Ok(self)
}
/// Installs the color-eyre panic and error report hooks.
///
/// This is a convenience method that sets up the color-eyre hooks for the terminal backend.
///
/// # Example
///
/// ```rust,no_run
/// use ratatui::backend::CrosstermBackend;
///
/// let backend = CrosstermBackend::stdout().with_color_eyre_hooks()?;
/// ```
#[cfg(feature = "color-eyre")]
pub fn with_color_eyre_hooks(self) -> color_eyre::Result<Self> {
use std::{io::stderr, panic};
use color_eyre::{config::HookBuilder, eyre};
let (panic, error) = HookBuilder::default().into_hooks();
let panic = panic.into_panic_hook();
let error = error.into_eyre_hook();
eyre::set_hook(Box::new(move |e| {
// ignore errors here because we are already in an error state
let _ = CrosstermBackend::reset(stderr());
error(e)
}))?;
panic::set_hook(Box::new(move |info| {
// ignore errors here because we are already in an error state
let _ = CrosstermBackend::reset(stderr());
panic(info);
}));
Ok(self)
}
/// Resets the terminal to its default state.
///
/// - Disables raw mode