2019-08-22 14:25:18 -04:00
|
|
|
/// Helper functions, especially to reproduce C std/posix functions
|
|
|
|
use nix::errno::*;
|
2019-08-22 16:44:47 -04:00
|
|
|
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;
|
2019-08-22 14:25:18 -04:00
|
|
|
use std::process::exit;
|
|
|
|
|
2019-08-22 16:44:47 -04:00
|
|
|
// 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;
|
|
|
|
|
2019-08-22 14:25:18 -04:00
|
|
|
/// 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)
|
2019-08-22 16:44:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|
2019-08-22 14:25:18 -04:00
|
|
|
}
|