fast_rich/
screen.rs

1//! Alternate screen support for full-screen terminal applications.
2//!
3//! Provides utilities for entering/exiting alternate screen buffer.
4
5use crossterm::{
6    cursor, execute,
7    terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
8};
9use std::io::{self, Write};
10
11/// Guard that automatically exits alternate screen when dropped.
12pub struct AlternateScreen {
13    active: bool,
14}
15
16impl AlternateScreen {
17    /// Enter the alternate screen.
18    pub fn enter() -> io::Result<Self> {
19        execute!(io::stdout(), EnterAlternateScreen)?;
20        terminal::enable_raw_mode()?;
21        execute!(io::stdout(), cursor::Hide)?;
22
23        Ok(AlternateScreen { active: true })
24    }
25
26    /// Manually exit the alternate screen.
27    pub fn exit(&mut self) -> io::Result<()> {
28        if self.active {
29            execute!(io::stdout(), cursor::Show)?;
30            terminal::disable_raw_mode()?;
31            execute!(io::stdout(), LeaveAlternateScreen)?;
32            self.active = false;
33        }
34        Ok(())
35    }
36
37    /// Check if alternate screen is active.
38    pub fn is_active(&self) -> bool {
39        self.active
40    }
41
42    /// Clear the alternate screen.
43    pub fn clear(&self) -> io::Result<()> {
44        execute!(
45            io::stdout(),
46            terminal::Clear(terminal::ClearType::All),
47            cursor::MoveTo(0, 0)
48        )?;
49        io::stdout().flush()
50    }
51
52    /// Get terminal size.
53    pub fn size(&self) -> io::Result<(u16, u16)> {
54        terminal::size()
55    }
56}
57
58impl Drop for AlternateScreen {
59    fn drop(&mut self) {
60        let _ = self.exit();
61    }
62}
63
64/// Run a function in alternate screen mode.
65pub fn with_alternate_screen<F, R>(f: F) -> io::Result<R>
66where
67    F: FnOnce(&AlternateScreen) -> io::Result<R>,
68{
69    let screen = AlternateScreen::enter()?;
70    let result = f(&screen);
71    drop(screen); // Explicit drop to exit alternate screen
72    result
73}
74
75#[cfg(test)]
76mod tests {
77    #[test]
78    fn test_alternate_screen_creation() {
79        // Can't easily test in CI, but we can verify the struct compiles
80        assert!(true);
81    }
82}