use ratatui::crossterm::{ event::{DisableMouseCapture, EnableMouseCapture}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use ratatui::prelude::*; use std::{ error::Error, io::{stdout, Stdout}, ops::{Deref, DerefMut}, }; pub type Result = std::result::Result>; pub struct Term { terminal: Terminal>, } impl Term { pub fn new() -> Result { let backend = CrosstermBackend::new(stdout()); let terminal = Terminal::new(backend)?; ratatui::crossterm::execute!(stdout(), EnterAlternateScreen, EnableMouseCapture)?; enable_raw_mode()?; // Shutdown gracefully let original_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |panic| { let _ = Self::stop(); original_hook(panic); eprint!("error: {panic}"); })); Ok(Self { terminal }) } pub fn stop() -> Result<()> { disable_raw_mode()?; ratatui::crossterm::execute!(stdout(), LeaveAlternateScreen, DisableMouseCapture)?; Ok(()) } } impl Deref for Term { type Target = Terminal>; fn deref(&self) -> &Self::Target { &self.terminal } } impl DerefMut for Term { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.terminal } } impl Drop for Term { fn drop(&mut self) { let _ = Term::stop(); } }