Setup Panic Hooks
When building TUIs with ratatui
, it’s vital to ensure that if your application encounters a panic,
it gracefully returns to the original terminal state. This prevents the terminal from getting stuck
in a modified state, which can be quite disruptive for users.
Here’s an example initialize_panic_handler
that works with crossterm
and with the Rust standard
library functionality and no external dependencies.
pub fn initialize_panic_handler() {
let original_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
crossterm::execute!(std::io::stderr(), crossterm::terminal::LeaveAlternateScreen).unwrap();
crossterm::terminal::disable_raw_mode().unwrap();
original_hook(panic_info);
}));
}
With this function, all your need to do is call initialize_panic_handler()
in main()
before
running any terminal initialization code:
fn main() -> Result<()> {
initialize_panic_handler();
// Startup
crossterm::terminal::enable_raw_mode()?;
crossterm::execute!(std::io::stderr(), crossterm::terminal::EnterAlternateScreen)?;
let mut terminal = Terminal::new(CrosstermBackend::new(std::io::stderr()))?;
// ...
// Shutdown
crossterm::execute!(std::io::stderr(), crossterm::terminal::LeaveAlternateScreen)?;
crossterm::terminal::disable_raw_mode()?;
Ok(())
}
We used crossterm
for panic handling. If you are using termion
you can do something like the
following:
use std::panic;
use std::error::Error;
pub fn initialize_panic_handler() {
let panic_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic| {
let panic_cleanup = || -> Result<(), Box<dyn Error>> {
let mut output = io::stderr();
write!(
output,
"{}{}{}",
termion::clear::All,
termion::screen::ToMainScreen,
termion::cursor::Show
)?;
output.into_raw_mode()?.suspend_raw_mode()?;
io::stderr().flush()?;
Ok(())
};
panic_cleanup().expect("failed to clean up for panic");
panic_hook(panic);
}));
}
As a general rule, you want to take the original panic hook and execute it after cleaning up the terminal. In the next sections we will discuss some third party packages that can help give better stacktraces.