Panic Hooks
Demonstrates the setting up panic hooks. Source panic.rs.
git clone https://github.com/ratatui/ratatui.git --branch latestcd ratatuicargo run -p panic
/// A Ratatui example that demonstrates how to handle panics in your application.////// Prior to Ratatui 0.28.1, a panic hook had to be manually set up to ensure that the terminal/// was reset when a panic occurred. This was necessary because a panic would interrupt the/// normal control flow and leave the terminal in a distorted state.////// Starting with Ratatui 0.28.1, the panic hook is automatically set up by the new/// `ratatui::init` function, so you no longer need to manually set up the panic hook. This/// example now demonstrates how the panic hook acts when it is enabled by default.////// When exiting normally or when handling `Result::Err`, we can reset the terminal manually at/// the end of `main` just before we print the error.////// Because a panic interrupts the normal control flow, manually resetting the terminal at the/// end of `main` won't do us any good. Instead, we need to make sure to set up a panic hook/// that first resets the terminal before handling the panic. This both reuses the standard/// panic hook to ensure a consistent panic handling UX and properly resets the terminal to not/// distort the output.////// That's why this example is set up to show both situations, with and without the panic hook,/// to see the difference.////// For more information on how to set this up manually, see the [Color Eyre recipe] in the/// Ratatui website.////// This example runs with the Ratatui library code in the branch that you are currently/// reading. See the [`latest`] branch for the code which works with the most recent Ratatui/// release.////// [`latest`]: https://github.com/ratatui/ratatui/tree/latest/// [Color Eyre recipe]: https://ratatui.rs/recipes/apps/color-eyreuse color_eyre::{eyre::bail, Result};use crossterm::event::{self, KeyCode};use ratatui::text::Line;use ratatui::widgets::{Block, Paragraph};use ratatui::Frame;
#[derive(Debug)]enum PanicHandlerState { Enabled, Disabled,}
fn main() -> Result<()> { color_eyre::install()?;
let mut panic_hook_state = PanicHandlerState::Enabled; ratatui::run(|terminal| loop { terminal.draw(|frame| render(frame, &panic_hook_state))?; if let Some(key) = event::read()?.as_key_press_event() { match key.code { KeyCode::Char('p') => panic!("intentional demo panic"), KeyCode::Char('e') => bail!("intentional demo error"), KeyCode::Char('h') => { let _ = std::panic::take_hook(); panic_hook_state = PanicHandlerState::Disabled; } KeyCode::Char('q') => return Ok(()), _ => {} } } })}
fn render(frame: &mut Frame, state: &PanicHandlerState) { let text = vec![ Line::from(format!("Panic hook is currently: {state:?}")), Line::from(""), Line::from("Press `p` to cause a panic"), Line::from("Press `e` to cause an error"), Line::from("Press `h` to disable the panic hook"), Line::from("Press `q` to quit"), Line::from(""), Line::from("When your app panics without a panic hook, you will likely have to"), Line::from("reset your terminal afterwards with the `reset` command"), Line::from(""), Line::from("Try first with the panic handler enabled, and then with it disabled"), Line::from("to see the difference"), ];
let paragraph = Paragraph::new(text) .block(Block::bordered().title("Panic Handler Demo")) .centered();
frame.render_widget(paragraph, frame.area());}