use ratatui::crossterm::{
event::{DisableBracketedPaste, DisableMouseCapture, EnableBracketedPaste, 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<T> = std::result::Result<T, Box<dyn Error>>;
pub struct Term {
terminal: Terminal<CrosstermBackend<Stdout>>,
}
impl Term {
pub fn new() -> Result<Self> {
let backend = CrosstermBackend::new(stdout());
let terminal = Terminal::new(backend)?;
ratatui::crossterm::execute!(
stdout(),
EnterAlternateScreen,
EnableMouseCapture,
EnableBracketedPaste
)?;
enable_raw_mode()?;
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,
DisableBracketedPaste
)?;
Ok(())
}
}
impl Deref for Term {
type Target = Terminal<CrosstermBackend<Stdout>>;
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();
}
}