Skip to main content

wiki_tui/
terminal.rs

1use anyhow::{Context, Result};
2use crossterm::{
3    cursor,
4    event::{DisableMouseCapture, EnableMouseCapture},
5    terminal::{EnterAlternateScreen, LeaveAlternateScreen},
6};
7use ratatui::prelude::CrosstermBackend as Backend;
8
9pub type Frame<'a> = ratatui::Frame<'a>;
10
11pub struct Tui {
12    pub terminal: ratatui::Terminal<Backend<std::io::Stdout>>,
13}
14
15impl Tui {
16    pub fn new() -> Result<Self> {
17        let terminal = ratatui::Terminal::new(Backend::new(std::io::stdout()))
18            .context("unable to create terminal")?;
19        Ok(Self { terminal })
20    }
21
22    pub fn enter(&mut self) -> Result<()> {
23        crossterm::terminal::enable_raw_mode()?;
24        crossterm::execute!(
25            std::io::stdout(),
26            EnterAlternateScreen,
27            EnableMouseCapture,
28            cursor::Hide
29        )?;
30        self.terminal.clear()?;
31        Ok(())
32    }
33
34    pub fn exit(&mut self) -> Result<()> {
35        self.terminal.clear()?;
36        crossterm::execute!(
37            std::io::stdout(),
38            LeaveAlternateScreen,
39            DisableMouseCapture,
40            cursor::Show
41        )?;
42        crossterm::terminal::disable_raw_mode()?;
43        Ok(())
44    }
45
46    pub fn suspend(&mut self) -> Result<()> {
47        self.exit()?;
48        #[cfg(windows)]
49        signal_hook::low_level::raise(signal_hook::consts::signal::SIGABRT)?;
50        #[cfg(not(windows))]
51        signal_hook::low_level::raise(signal_hook::consts::signal::SIGSTOP)?;
52        Ok(())
53    }
54
55    pub fn resume(&mut self) -> Result<()> {
56        self.enter()?;
57        Ok(())
58    }
59}