pub mod layout;
pub mod nav;
pub mod theme;
pub mod widgets;
use std::io::{self, Stdout};
use crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{backend::CrosstermBackend, layout::Rect, Frame, Terminal};
pub struct TerminalManager {
terminal: Terminal<CrosstermBackend<Stdout>>,
}
impl TerminalManager {
pub fn new() -> anyhow::Result<Self> {
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, crossterm::cursor::Hide)?;
let backend = CrosstermBackend::new(stdout);
let terminal = Terminal::new(backend)?;
Ok(Self { terminal })
}
pub fn restore(&mut self) -> anyhow::Result<()> {
disable_raw_mode()?;
execute!(
self.terminal.backend_mut(),
LeaveAlternateScreen,
crossterm::cursor::Show
)?;
Ok(())
}
pub fn draw<F>(&mut self, f: F) -> anyhow::Result<()>
where
F: FnOnce(&mut Frame),
{
self.terminal.draw(f)?;
Ok(())
}
pub fn size(&self) -> anyhow::Result<Rect> {
Ok(self.terminal.size()?.into())
}
}
impl Drop for TerminalManager {
fn drop(&mut self) {
let _ = self.restore();
}
}
pub fn install_panic_hook() {
let original_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
let _ = disable_raw_mode();
let _ = execute!(io::stdout(), LeaveAlternateScreen, crossterm::cursor::Show);
original_hook(panic_info);
}));
}