use crossterm::{
cursor, execute,
terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::io::{self, Write};
pub struct AlternateScreen {
active: bool,
}
impl AlternateScreen {
pub fn enter() -> io::Result<Self> {
execute!(io::stdout(), EnterAlternateScreen)?;
terminal::enable_raw_mode()?;
execute!(io::stdout(), cursor::Hide)?;
Ok(AlternateScreen { active: true })
}
pub fn exit(&mut self) -> io::Result<()> {
if self.active {
execute!(io::stdout(), cursor::Show)?;
terminal::disable_raw_mode()?;
execute!(io::stdout(), LeaveAlternateScreen)?;
self.active = false;
}
Ok(())
}
pub fn is_active(&self) -> bool {
self.active
}
pub fn clear(&self) -> io::Result<()> {
execute!(
io::stdout(),
terminal::Clear(terminal::ClearType::All),
cursor::MoveTo(0, 0)
)?;
io::stdout().flush()
}
pub fn size(&self) -> io::Result<(u16, u16)> {
terminal::size()
}
}
impl Drop for AlternateScreen {
fn drop(&mut self) {
let _ = self.exit();
}
}
pub fn with_alternate_screen<F, R>(f: F) -> io::Result<R>
where
F: FnOnce(&AlternateScreen) -> io::Result<R>,
{
let screen = AlternateScreen::enter()?;
let result = f(&screen);
drop(screen); result
}
#[cfg(test)]
mod tests {
#[test]
fn test_alternate_screen_creation() {
}
}