/// Helper functions, especially to reproduce C std/posix functions use nix::errno::*; use nix::Error as NixError; use nix::sys::termios; use nix::sys::termios::{ ControlFlags, InputFlags, LocalFlags, OutputFlags, SpecialCharacterIndices, Termios }; use std::io::Error; use std::os::unix::io::RawFd; use std::process::exit; // Redefine the posix constants for rust land pub const STDIN_FILENO: i32 = 0; // pub const STDOUT_FILENO: i32 = 1; // pub const STDERR_FILENO: i32 = 2; /// Is this character an ASCII control character? pub fn is_cntrl(c: char) -> bool { let code = c as u8; code < 32 || code == 127 } pub fn die(code: &Errno, msg: &str) -> ! { eprintln!("{:?} ({})", code, msg); exit(1) } pub fn get_termios(fd: RawFd) -> Termios { termios::tcgetattr(fd).unwrap() } pub fn enable_raw_mode() -> Result<(), Error> { let mut raw = get_termios(STDIN_FILENO); raw.input_flags.remove( InputFlags::BRKINT & InputFlags::IGNCR & InputFlags::IGNBRK & InputFlags::ICRNL & InputFlags::INLCR & InputFlags::INPCK & InputFlags::ISTRIP & InputFlags::IXON & InputFlags::PARMRK ); raw.output_flags.remove(OutputFlags::OPOST); raw.local_flags.remove( LocalFlags::ECHO & LocalFlags::ECHONL & LocalFlags::ICANON & LocalFlags::IEXTEN & LocalFlags::ISIG ); raw.control_flags.remove( ControlFlags::CSIZE & ControlFlags::PARENB ); // 8 bit characters raw.control_flags |= termios::ControlFlags::CS8; raw.control_chars[SpecialCharacterIndices::VMIN as usize] = 0; raw.control_chars[SpecialCharacterIndices::VTIME as usize] = 1; match termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, &raw) { Ok(()) => Ok(()), Err(e) => match e.as_errno() { Some(errno) => die(&errno, "tcsetattr"), None => panic!("Failed to enable raw mode") } } } pub fn disable_raw_mode(original: &Termios) -> Result<(), Error> { match termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, original) { Ok(()) => Ok(()), Err(E) => match E.as_errno() { Some(errno) => die(&errno, "tcsetattr"), None => panic!("Failed to disable raw mode") } } }