1use crossterm::{
6 cursor, execute,
7 terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
8};
9use std::io::{self, Write};
10
11pub struct AlternateScreen {
13 active: bool,
14}
15
16impl AlternateScreen {
17 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 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 pub fn is_active(&self) -> bool {
39 self.active
40 }
41
42 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 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
64pub 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); result
73}
74
75#[cfg(test)]
76mod tests {
77 #[test]
78 fn test_alternate_screen_creation() {
79 assert!(true);
81 }
82}