diff options
author | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
commit | a990de90fe41456a23e58bd087d2f107d321f3a1 (patch) | |
tree | 15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/console/src/unix_term.rs | |
parent | 3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff) | |
download | fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip |
Deleted vendor folder
Diffstat (limited to 'vendor/console/src/unix_term.rs')
-rw-r--r-- | vendor/console/src/unix_term.rs | 362 |
1 files changed, 0 insertions, 362 deletions
diff --git a/vendor/console/src/unix_term.rs b/vendor/console/src/unix_term.rs deleted file mode 100644 index 8e1e592..0000000 --- a/vendor/console/src/unix_term.rs +++ /dev/null @@ -1,362 +0,0 @@ -use std::env; -use std::fmt::Display; -use std::fs; -use std::io; -use std::io::{BufRead, BufReader}; -use std::mem; -use std::os::unix::io::AsRawFd; -use std::ptr; -use std::str; - -use crate::kb::Key; -use crate::term::Term; - -pub use crate::common_term::*; - -pub const DEFAULT_WIDTH: u16 = 80; - -#[inline] -pub fn is_a_terminal(out: &Term) -> bool { - unsafe { libc::isatty(out.as_raw_fd()) != 0 } -} - -pub fn is_a_color_terminal(out: &Term) -> bool { - if !is_a_terminal(out) { - return false; - } - - if env::var("NO_COLOR").is_ok() { - return false; - } - - match env::var("TERM") { - Ok(term) => term != "dumb", - Err(_) => false, - } -} - -pub fn c_result<F: FnOnce() -> libc::c_int>(f: F) -> io::Result<()> { - let res = f(); - if res != 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) - } -} - -pub fn terminal_size(out: &Term) -> Option<(u16, u16)> { - unsafe { - if libc::isatty(libc::STDOUT_FILENO) != 1 { - return None; - } - - let mut winsize: libc::winsize = std::mem::zeroed(); - - // FIXME: ".into()" used as a temporary fix for a libc bug - // https://github.com/rust-lang/libc/pull/704 - #[allow(clippy::useless_conversion)] - libc::ioctl(out.as_raw_fd(), libc::TIOCGWINSZ.into(), &mut winsize); - if winsize.ws_row > 0 && winsize.ws_col > 0 { - Some((winsize.ws_row as u16, winsize.ws_col as u16)) - } else { - None - } - } -} - -pub fn read_secure() -> io::Result<String> { - let f_tty; - let fd = unsafe { - if libc::isatty(libc::STDIN_FILENO) == 1 { - f_tty = None; - libc::STDIN_FILENO - } else { - let f = fs::OpenOptions::new() - .read(true) - .write(true) - .open("/dev/tty")?; - let fd = f.as_raw_fd(); - f_tty = Some(BufReader::new(f)); - fd - } - }; - - let mut termios = core::mem::MaybeUninit::uninit(); - c_result(|| unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) })?; - let mut termios = unsafe { termios.assume_init() }; - let original = termios; - termios.c_lflag &= !libc::ECHO; - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSAFLUSH, &termios) })?; - let mut rv = String::new(); - - let read_rv = if let Some(mut f) = f_tty { - f.read_line(&mut rv) - } else { - io::stdin().read_line(&mut rv) - }; - - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSAFLUSH, &original) })?; - - read_rv.map(|_| { - let len = rv.trim_end_matches(&['\r', '\n'][..]).len(); - rv.truncate(len); - rv - }) -} - -fn poll_fd(fd: i32, timeout: i32) -> io::Result<bool> { - let mut pollfd = libc::pollfd { - fd, - events: libc::POLLIN, - revents: 0, - }; - let ret = unsafe { libc::poll(&mut pollfd as *mut _, 1, timeout) }; - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(pollfd.revents & libc::POLLIN != 0) - } -} - -#[cfg(target_os = "macos")] -fn select_fd(fd: i32, timeout: i32) -> io::Result<bool> { - unsafe { - let mut read_fd_set: libc::fd_set = mem::zeroed(); - - let mut timeout_val; - let timeout = if timeout < 0 { - ptr::null_mut() - } else { - timeout_val = libc::timeval { - tv_sec: (timeout / 1000) as _, - tv_usec: (timeout * 1000) as _, - }; - &mut timeout_val - }; - - libc::FD_ZERO(&mut read_fd_set); - libc::FD_SET(fd, &mut read_fd_set); - let ret = libc::select( - fd + 1, - &mut read_fd_set, - ptr::null_mut(), - ptr::null_mut(), - timeout, - ); - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(libc::FD_ISSET(fd, &read_fd_set)) - } - } -} - -fn select_or_poll_term_fd(fd: i32, timeout: i32) -> io::Result<bool> { - // There is a bug on macos that ttys cannot be polled, only select() - // works. However given how problematic select is in general, we - // normally want to use poll there too. - #[cfg(target_os = "macos")] - { - if unsafe { libc::isatty(fd) == 1 } { - return select_fd(fd, timeout); - } - } - poll_fd(fd, timeout) -} - -fn read_single_char(fd: i32) -> io::Result<Option<char>> { - // timeout of zero means that it will not block - let is_ready = select_or_poll_term_fd(fd, 0)?; - - if is_ready { - // if there is something to be read, take 1 byte from it - let mut buf: [u8; 1] = [0]; - - read_bytes(fd, &mut buf, 1)?; - Ok(Some(buf[0] as char)) - } else { - //there is nothing to be read - Ok(None) - } -} - -// Similar to libc::read. Read count bytes into slice buf from descriptor fd. -// If successful, return the number of bytes read. -// Will return an error if nothing was read, i.e when called at end of file. -fn read_bytes(fd: i32, buf: &mut [u8], count: u8) -> io::Result<u8> { - let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, count as usize) }; - if read < 0 { - Err(io::Error::last_os_error()) - } else if read == 0 { - Err(io::Error::new( - io::ErrorKind::UnexpectedEof, - "Reached end of file", - )) - } else if buf[0] == b'\x03' { - Err(io::Error::new( - io::ErrorKind::Interrupted, - "read interrupted", - )) - } else { - Ok(read as u8) - } -} - -fn read_single_key_impl(fd: i32) -> Result<Key, io::Error> { - loop { - match read_single_char(fd)? { - Some('\x1b') => { - // Escape was read, keep reading in case we find a familiar key - break if let Some(c1) = read_single_char(fd)? { - if c1 == '[' { - if let Some(c2) = read_single_char(fd)? { - match c2 { - 'A' => Ok(Key::ArrowUp), - 'B' => Ok(Key::ArrowDown), - 'C' => Ok(Key::ArrowRight), - 'D' => Ok(Key::ArrowLeft), - 'H' => Ok(Key::Home), - 'F' => Ok(Key::End), - 'Z' => Ok(Key::BackTab), - _ => { - let c3 = read_single_char(fd)?; - if let Some(c3) = c3 { - if c3 == '~' { - match c2 { - '1' => Ok(Key::Home), // tmux - '2' => Ok(Key::Insert), - '3' => Ok(Key::Del), - '4' => Ok(Key::End), // tmux - '5' => Ok(Key::PageUp), - '6' => Ok(Key::PageDown), - '7' => Ok(Key::Home), // xrvt - '8' => Ok(Key::End), // xrvt - _ => Ok(Key::UnknownEscSeq(vec![c1, c2, c3])), - } - } else { - Ok(Key::UnknownEscSeq(vec![c1, c2, c3])) - } - } else { - // \x1b[ and 1 more char - Ok(Key::UnknownEscSeq(vec![c1, c2])) - } - } - } - } else { - // \x1b[ and no more input - Ok(Key::UnknownEscSeq(vec![c1])) - } - } else { - // char after escape is not [ - Ok(Key::UnknownEscSeq(vec![c1])) - } - } else { - //nothing after escape - Ok(Key::Escape) - }; - } - Some(c) => { - let byte = c as u8; - let mut buf: [u8; 4] = [byte, 0, 0, 0]; - - break if byte & 224u8 == 192u8 { - // a two byte unicode character - read_bytes(fd, &mut buf[1..], 1)?; - Ok(key_from_utf8(&buf[..2])) - } else if byte & 240u8 == 224u8 { - // a three byte unicode character - read_bytes(fd, &mut buf[1..], 2)?; - Ok(key_from_utf8(&buf[..3])) - } else if byte & 248u8 == 240u8 { - // a four byte unicode character - read_bytes(fd, &mut buf[1..], 3)?; - Ok(key_from_utf8(&buf[..4])) - } else { - Ok(match c { - '\n' | '\r' => Key::Enter, - '\x7f' => Key::Backspace, - '\t' => Key::Tab, - '\x01' => Key::Home, // Control-A (home) - '\x05' => Key::End, // Control-E (end) - '\x08' => Key::Backspace, // Control-H (8) (Identical to '\b') - _ => Key::Char(c), - }) - }; - } - None => { - // there is no subsequent byte ready to be read, block and wait for input - // negative timeout means that it will block indefinitely - match select_or_poll_term_fd(fd, -1) { - Ok(_) => continue, - Err(_) => break Err(io::Error::last_os_error()), - } - } - } - } -} - -pub fn read_single_key() -> io::Result<Key> { - let tty_f; - let fd = unsafe { - if libc::isatty(libc::STDIN_FILENO) == 1 { - libc::STDIN_FILENO - } else { - tty_f = fs::OpenOptions::new() - .read(true) - .write(true) - .open("/dev/tty")?; - tty_f.as_raw_fd() - } - }; - let mut termios = core::mem::MaybeUninit::uninit(); - c_result(|| unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) })?; - let mut termios = unsafe { termios.assume_init() }; - let original = termios; - unsafe { libc::cfmakeraw(&mut termios) }; - termios.c_oflag = original.c_oflag; - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSADRAIN, &termios) })?; - let rv: io::Result<Key> = read_single_key_impl(fd); - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSADRAIN, &original) })?; - - // if the user hit ^C we want to signal SIGINT to outselves. - if let Err(ref err) = rv { - if err.kind() == io::ErrorKind::Interrupted { - unsafe { - libc::raise(libc::SIGINT); - } - } - } - - rv -} - -pub fn key_from_utf8(buf: &[u8]) -> Key { - if let Ok(s) = str::from_utf8(buf) { - if let Some(c) = s.chars().next() { - return Key::Char(c); - } - } - Key::Unknown -} - -#[cfg(not(target_os = "macos"))] -lazy_static::lazy_static! { - static ref IS_LANG_UTF8: bool = match std::env::var("LANG") { - Ok(lang) => lang.to_uppercase().ends_with("UTF-8"), - _ => false, - }; -} - -#[cfg(target_os = "macos")] -pub fn wants_emoji() -> bool { - true -} - -#[cfg(not(target_os = "macos"))] -pub fn wants_emoji() -> bool { - *IS_LANG_UTF8 -} - -pub fn set_title<T: Display>(title: T) { - print!("\x1b]0;{}\x07", title); -} |