From f20c9751c4ae830a36388022fc4e783653e82abf Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sun, 16 Jun 2024 15:50:57 -0700 Subject: [PATCH] fix: add std panic hook --- src/backend/crossterm.rs | 63 +++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/src/backend/crossterm.rs b/src/backend/crossterm.rs index 347e6e4e..0daeba61 100644 --- a/src/backend/crossterm.rs +++ b/src/backend/crossterm.rs @@ -28,7 +28,6 @@ use crate::{ }, layout::{Rect, Size}, style::{Color, Modifier, Style}, - Terminal, TerminalOptions, }; /// A [`Backend`] implementation that uses [Crossterm] to render to the terminal. @@ -181,7 +180,7 @@ impl CrosstermBackend { /// # std::io::Result::Ok(()) /// ``` pub fn stdout_with_defaults() -> io::Result { - Self::stdout().with_raw_mode()?.with_alternate_screen() + Self::stdout().with_defaults() } } @@ -216,14 +215,38 @@ impl CrosstermBackend { /// # std::io::Result::Ok(()) /// ``` pub fn stderr_with_defaults() -> io::Result { - let backend = Self::stderr().with_raw_mode()?.with_alternate_screen()?; - #[cfg(feature = "color-eyre")] - let backend = backend.with_color_eyre_hooks()?; - Ok(backend) + Self::stderr().with_defaults() } } impl CrosstermBackend { + /// Enables default settings for the terminal backend. + /// + /// This enables raw mode and switches to the alternate screen. Mouse support is not enabled. + /// + /// If the `color-eyre` feature is enabled, the color-eyre panic and error report hooks are + /// installed. Otherwise, a panic hook is installed that resets the terminal to its default + /// state before panicking. + /// + /// Returns an [`io::Result`] containing self so that it can be chained with other methods. + /// + /// # Example + /// + /// ```rust,no_run + /// use ratatui::backend::CrosstermBackend; + /// + /// let backend = CrosstermBackend::stdout().with_defaults()?; + /// # std::io::Result::Ok(()) + /// ``` + pub fn with_defaults(mut self) -> io::Result { + let backend = self.with_raw_mode()?.with_alternate_screen()?; + #[cfg(feature = "color-eyre")] + let backend = backend.with_color_eyre_hooks()?; + #[cfg(not(feature = "color-eyre"))] + let backend = backend.with_panic_hook()?; + Ok(backend) + } + /// Enables raw mode for the terminal. /// /// Returns an [`io::Result`] containing self so that it can be chained with other methods. @@ -341,6 +364,29 @@ impl CrosstermBackend { Ok(self) } + /// Installs a panic hook that resets the terminal to its default state before panicking. + /// + /// This is a convenience method that sets up the panic hook for the terminal backend. + /// + /// # Example + /// + /// ```rust,no_run + /// use ratatui::backend::CrosstermBackend; + /// + /// let backend = CrosstermBackend::stdout().with_panic_hook()?; + /// ``` + #[cfg(not(feature = "color-eyre"))] + pub fn with_panic_hook(self) -> io::Result { + use std::panic; + + let hook = panic::take_hook(); + panic::set_hook(Box::new(move |info| { + let _ = CrosstermBackend::reset(io::stderr()); + hook(info); + })); + 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. @@ -353,7 +399,7 @@ impl CrosstermBackend { /// let backend = CrosstermBackend::stdout().with_color_eyre_hooks()?; /// ``` #[cfg(feature = "color-eyre")] - pub fn with_color_eyre_hooks(self) -> color_eyre::Result { + pub fn with_color_eyre_hooks(self) -> io::Result { use std::{io::stderr, panic}; use color_eyre::{config::HookBuilder, eyre}; @@ -365,7 +411,8 @@ impl CrosstermBackend { // ignore errors here because we are already in an error state let _ = CrosstermBackend::reset(stderr()); error(e) - }))?; + })) + .map_err(|error| io::Error::other(error))?; panic::set_hook(Box::new(move |info| { // ignore errors here because we are already in an error state let _ = CrosstermBackend::reset(stderr());