Raw read_char for unix (#89)

This commit is contained in:
scauligi 2019-02-16 01:50:42 -08:00 committed by Timon
parent 3d92f62be4
commit 8ffdb00b10
2 changed files with 56 additions and 3 deletions

View File

@ -1,7 +1,7 @@
//! This is a UNIX specific implementation for input related action. //! This is a UNIX specific implementation for input related action.
use super::*; use super::*;
use crate::sys::unix::{get_tty, read_char}; use crate::sys::unix::{get_tty, read_char, read_char_raw};
use crossterm_utils::TerminalOutput; use crossterm_utils::TerminalOutput;
use std::char; use std::char;
@ -16,8 +16,17 @@ impl UnixInput {
} }
impl ITerminalInput for UnixInput { impl ITerminalInput for UnixInput {
fn read_char(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> { fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> {
read_char() let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false,
};
if is_raw_screen {
read_char_raw()
} else {
read_char()
}
} }
fn read_async(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader { fn read_async(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader {

View File

@ -68,3 +68,47 @@ pub fn read_char() -> io::Result<char> {
rv rv
} }
fn get_tty_fd() -> io::Result<i32> {
let fd = unsafe {
if libc::isatty(libc::STDIN_FILENO) == 1 {
libc::STDIN_FILENO
} else {
let tty_f = fs::File::open("/dev/tty")?;
tty_f.as_raw_fd()
}
};
Ok(fd)
}
pub fn read_char_raw() -> io::Result<char> {
let mut buf = [0u8; 20];
let fd = get_tty_fd()?;
// read input and convert it to char
let rv = unsafe {
let read = libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, 20);
if read < 0 {
Err(io::Error::last_os_error())
} else {
let mut pressed_char = Ok(' ');
if let Ok(s) = ::std::str::from_utf8(&buf[..read as usize]) {
if let Some(c) = s.chars().next() {
pressed_char = Ok(c);
}
} else {
pressed_char = Err(io::Error::new(
io::ErrorKind::Interrupted,
"Could not parse char to utf8 char",
));
}
pressed_char
}
};
rv
}