use std::io;
use std::os::fd::AsFd;
use nix::sys::termios::{self, SetArg, Termios};
fn save_terminal_state() -> io::Result<Termios> {
termios::tcgetattr(io::stdin().as_fd()).map_err(|e| io::Error::other(e.to_string()))
}
fn restore_terminal_state(saved: &Termios) {
let _ = termios::tcsetattr(io::stdin().as_fd(), SetArg::TCSANOW, saved);
}
pub(super) struct TerminalStateGuard {
saved: Termios,
active: bool,
}
impl TerminalStateGuard {
pub(super) fn new() -> io::Result<Self> {
let saved = save_terminal_state()?;
Ok(Self {
saved,
active: false,
})
}
pub(super) fn activate_raw_mode(&mut self) -> io::Result<()> {
let mut raw = self.saved.clone();
termios::cfmakeraw(&mut raw);
termios::tcsetattr(io::stdin().as_fd(), SetArg::TCSANOW, &raw)
.map_err(|e| io::Error::other(e.to_string()))?;
self.active = true;
Ok(())
}
}
impl Drop for TerminalStateGuard {
fn drop(&mut self) {
if self.active {
restore_terminal_state(&self.saved);
}
}
}