use std::io;
pub struct RawModeGuard {
#[cfg(unix)]
prev: Option<libc::termios>,
}
impl RawModeGuard {
#[cfg(unix)]
pub fn suspend(&self) -> io::Result<impl Drop + '_> {
unsafe {
let mut current: libc::termios = std::mem::zeroed();
if libc::tcgetattr(libc::STDIN_FILENO, &mut current) != 0 {
return Err(io::Error::last_os_error());
}
let saved = self
.prev
.as_ref()
.expect("a live guard retains its snapshot");
if libc::tcsetattr(libc::STDIN_FILENO, libc::TCSANOW, saved) != 0 {
return Err(io::Error::last_os_error());
}
Ok(Self {
prev: Some(current),
})
}
}
pub fn enter() -> io::Result<Self> {
#[cfg(unix)]
{
let prev = unsafe {
let fd = libc::STDIN_FILENO;
let mut prev: libc::termios = std::mem::zeroed();
if libc::tcgetattr(fd, &mut prev) != 0 {
return Err(io::Error::last_os_error());
}
let mut raw = prev;
libc::cfmakeraw(&mut raw);
if libc::tcsetattr(fd, libc::TCSANOW, &raw) != 0 {
return Err(io::Error::last_os_error());
}
prev
};
Ok(Self { prev: Some(prev) })
}
#[cfg(not(unix))]
{
crossterm::terminal::enable_raw_mode()?;
Ok(Self {})
}
}
}
impl Drop for RawModeGuard {
fn drop(&mut self) {
#[cfg(unix)]
if let Some(prev) = self.prev.take() {
unsafe {
libc::tcsetattr(libc::STDIN_FILENO, libc::TCSANOW, &prev);
}
}
#[cfg(not(unix))]
let _ = crossterm::terminal::disable_raw_mode();
}
}