From 44cb4d3d2f1e9b31078346556185cc38948841c4 Mon Sep 17 00:00:00 2001 From: Karl Date: Wed, 9 Aug 2023 13:54:48 -0400 Subject: [PATCH] Add panic hook to not mess terminal upon panic (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adds panic hook to not mess terminal upon panic. * Define a reset function for the panic hook --------- Co-authored-by: Orhun Parmaksız --- src/tui.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/tui.rs b/src/tui.rs index 635ccb8..1cd331a 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -4,6 +4,7 @@ use crate::ui; use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}; use std::io; +use std::panic; use tui::backend::Backend; use tui::Terminal; @@ -31,6 +32,15 @@ impl Tui { pub fn init(&mut self) -> AppResult<()> { terminal::enable_raw_mode()?; crossterm::execute!(io::stderr(), EnterAlternateScreen, EnableMouseCapture)?; + + // Define a custom panic hook to reset the terminal properties. + // This way, you won't have your terminal messed up if an unexpected error happens. + let panic_hook = panic::take_hook(); + panic::set_hook(Box::new(move |panic| { + Self::reset().expect("failed to reset the terminal"); + panic_hook(panic); + })); + self.terminal.hide_cursor()?; self.terminal.clear()?; Ok(()) @@ -45,12 +55,21 @@ impl Tui { Ok(()) } + /// Resets the terminal interface. + /// + /// This function is also used for the panic hook to revert + /// the terminal properties if unexpected errors occur. + fn reset() -> AppResult<()> { + terminal::disable_raw_mode()?; + crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?; + Ok(()) + } + /// Exits the terminal interface. /// /// It disables the raw mode and reverts back the terminal properties. pub fn exit(&mut self) -> AppResult<()> { - terminal::disable_raw_mode()?; - crossterm::execute!(io::stderr(), LeaveAlternateScreen, DisableMouseCapture)?; + Self::reset()?; self.terminal.show_cursor()?; Ok(()) }