use std::io;
use crossterm::{execute, terminal};
use log::*;
#[derive(Debug)]
pub struct TerminalRawModeScope {
is_enabled: bool,
is_alt_screen_enabled: bool,
is_reset: bool,
}
impl TerminalRawModeScope {
pub fn new(enable: bool) -> io::Result<Self> {
Self::enable(enable)?;
Ok(Self {
is_enabled: enable,
is_alt_screen_enabled: false,
is_reset: false,
})
}
pub fn new_with_alternate_screen() -> io::Result<Self> {
Self::enable(true)?;
Self::enable_alternate_screen(true)?;
Ok(Self {
is_enabled: true,
is_alt_screen_enabled: true,
is_reset: false,
})
}
pub fn reset(&mut self) -> io::Result<()> {
if self.is_reset {
return Ok(());
}
Self::enable(!self.is_enabled)?;
if self.is_alt_screen_enabled {
Self::enable_alternate_screen(false)?;
}
self.is_reset = true;
Ok(())
}
fn enable(enable: bool) -> io::Result<()> {
debug!("TerminalRawModeScope.enable({enable})");
if enable {
terminal::enable_raw_mode()
} else {
terminal::disable_raw_mode()
}
}
fn enable_alternate_screen(enable: bool) -> io::Result<()> {
debug!("TerminalRawModeScope.enable_alternate_screen({enable})");
if enable {
execute!(io::stdout(), terminal::EnterAlternateScreen)
} else {
execute!(io::stdout(), terminal::LeaveAlternateScreen)
}
}
}
impl Drop for TerminalRawModeScope {
fn drop(&mut self) {
if let Err(error) = self.reset() {
warn!("Failed to change terminal raw mode, ignored: {error}");
}
}
}