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::sys::termios;
|
|
|
|
use nix::sys::termios::{
|
2019-08-23 13:33:18 -04:00
|
|
|
ControlFlags, InputFlags, LocalFlags, OutputFlags, SpecialCharacterIndices, Termios,
|
2019-08-22 16:44:47 -04:00
|
|
|
};
|
2019-08-23 13:33:18 -04:00
|
|
|
use nix::Error as NixError;
|
2019-08-22 16:44:47 -04:00
|
|
|
|
|
|
|
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
|
2019-08-23 14:57:26 -04:00
|
|
|
|
|
|
|
/// The value of the raw file descriptor for STDIN
|
2019-08-22 16:44:47 -04:00
|
|
|
pub const STDIN_FILENO: i32 = 0;
|
|
|
|
// pub const STDOUT_FILENO: i32 = 1;
|
|
|
|
// pub const STDERR_FILENO: i32 = 2;
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
/// Convert Ctrl+letter chords to their
|
|
|
|
/// ASCII table equivalents
|
|
|
|
#[inline]
|
|
|
|
pub fn ctrl_key(c: char) -> char {
|
|
|
|
let key = c as u8;
|
|
|
|
|
|
|
|
if !c.is_ascii() {
|
|
|
|
panic!("CTRL_KEY only accepts ASCII characters");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Intentionally "overflow" u8 to wrap around to the
|
|
|
|
// beginning of the ASCII table. Ctrl+a is 1, Ctrl+b is 2, etc.
|
|
|
|
(key & 0x1f) as char
|
|
|
|
}
|
|
|
|
|
2019-08-22 14:25:18 -04:00
|
|
|
pub fn die(code: &Errno, msg: &str) -> ! {
|
|
|
|
eprintln!("{:?} ({})", code, msg);
|
|
|
|
|
|
|
|
exit(1)
|
2019-08-22 16:44:47 -04:00
|
|
|
}
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
/// Get a `Termios` struct, for getting/setting terminal flags
|
2019-08-22 16:44:47 -04:00
|
|
|
pub fn get_termios(fd: RawFd) -> Termios {
|
|
|
|
termios::tcgetattr(fd).unwrap()
|
|
|
|
}
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
/// Put terminal into raw mode so there is full control of terminal output
|
|
|
|
pub fn enable_raw_mode() {
|
2019-08-22 16:44:47 -04:00
|
|
|
let mut raw = get_termios(STDIN_FILENO);
|
|
|
|
|
|
|
|
raw.input_flags.remove(
|
2019-08-23 13:33:18 -04:00
|
|
|
InputFlags::BRKINT
|
|
|
|
| InputFlags::IGNCR
|
|
|
|
| InputFlags::IGNBRK
|
|
|
|
| InputFlags::ICRNL
|
|
|
|
| InputFlags::INLCR
|
|
|
|
| InputFlags::INPCK
|
|
|
|
| InputFlags::ISTRIP
|
|
|
|
| InputFlags::IXON
|
|
|
|
| InputFlags::PARMRK,
|
2019-08-22 16:44:47 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
raw.output_flags.remove(OutputFlags::OPOST);
|
|
|
|
|
|
|
|
raw.local_flags.remove(
|
2019-08-23 13:33:18 -04:00
|
|
|
LocalFlags::ECHO
|
|
|
|
| LocalFlags::ECHONL
|
|
|
|
| LocalFlags::ICANON
|
|
|
|
| LocalFlags::IEXTEN
|
|
|
|
| LocalFlags::ISIG,
|
2019-08-22 16:44:47 -04:00
|
|
|
);
|
|
|
|
|
2019-08-23 13:33:18 -04:00
|
|
|
raw.control_flags
|
|
|
|
.remove(ControlFlags::CSIZE | ControlFlags::PARENB);
|
2019-08-22 16:44:47 -04:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
// Raw mode or bust!
|
|
|
|
termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, &raw).unwrap();
|
2019-08-22 16:44:47 -04:00
|
|
|
}
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
/// Restore terminal to "cooked"/canonical mode
|
|
|
|
pub fn disable_raw_mode(original: &Termios) {
|
|
|
|
termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, original).unwrap();
|
2019-08-23 13:33:18 -04:00
|
|
|
}
|