From dd845e949ac59e08bf12d0fcac8b4069c5c7645c Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 9 Mar 2021 02:33:01 -0500 Subject: add async implementation of Input this is just copied and pasted for now, need to figure out how to generate one from the other --- src/blocking/input.rs | 247 +++++++++++++------------------------------------- src/blocking/mod.rs | 3 +- 2 files changed, 66 insertions(+), 184 deletions(-) (limited to 'src/blocking') diff --git a/src/blocking/input.rs b/src/blocking/input.rs index bc4f401..716cfca 100644 --- a/src/blocking/input.rs +++ b/src/blocking/input.rs @@ -1,111 +1,4 @@ use std::io::Read as _; -use std::os::unix::io::AsRawFd as _; - -#[derive(Eq, PartialEq, Debug, Clone)] -pub enum Key { - String(String), - Char(char), - Bytes(Vec), - Byte(u8), - Ctrl(u8), - Meta(u8), - Backspace, - Escape, - Up, - Down, - Right, - Left, - KeypadUp, - KeypadDown, - KeypadRight, - KeypadLeft, - Home, - End, - Insert, - Delete, - PageUp, - PageDown, - F(u8), -} - -impl Key { - pub fn into_bytes(self) -> Vec { - use Key::*; - match self { - String(s) => s.into_bytes(), - Char(c) => c.to_string().into_bytes(), - Bytes(s) => s, - Byte(c) => vec![c], - Ctrl(c) => vec![c - b'a' + 1], - Meta(c) => vec![b'\x1b', c], - Backspace => b"\x7f".to_vec(), - Escape => b"\x1b".to_vec(), - Up => b"\x1b[A".to_vec(), - Down => b"\x1b[B".to_vec(), - Right => b"\x1b[C".to_vec(), - Left => b"\x1b[D".to_vec(), - KeypadUp => b"\x1bOA".to_vec(), - KeypadDown => b"\x1bOB".to_vec(), - KeypadRight => b"\x1bOC".to_vec(), - KeypadLeft => b"\x1bOD".to_vec(), - Home => b"\x1b[H".to_vec(), - End => b"\x1b[F".to_vec(), - Insert => b"\x1b[2~".to_vec(), - Delete => b"\x1b[3~".to_vec(), - PageUp => b"\x1b[5~".to_vec(), - PageDown => b"\x1b[6~".to_vec(), - F(c) => match c { - 1 => b"\x1bOP".to_vec(), - 2 => b"\x1bOQ".to_vec(), - 3 => b"\x1bOR".to_vec(), - 4 => b"\x1bOS".to_vec(), - 5 => b"\x1b[15~".to_vec(), - 6 => b"\x1b[17~".to_vec(), - 7 => b"\x1b[18~".to_vec(), - 8 => b"\x1b[19~".to_vec(), - 9 => b"\x1b[20~".to_vec(), - 10 => b"\x1b[21~".to_vec(), - 11 => b"\x1b[23~".to_vec(), - 12 => b"\x1b[24~".to_vec(), - 13 => b"\x1b[25~".to_vec(), - 14 => b"\x1b[26~".to_vec(), - 15 => b"\x1b[28~".to_vec(), - 16 => b"\x1b[29~".to_vec(), - 17 => b"\x1b[31~".to_vec(), - 18 => b"\x1b[32~".to_vec(), - 19 => b"\x1b[33~".to_vec(), - 20 => b"\x1b[34~".to_vec(), - _ => vec![], - }, - } - } -} - -pub struct RawGuard { - termios: nix::sys::termios::Termios, - cleaned_up: bool, -} - -impl RawGuard { - pub fn cleanup(&mut self) { - if self.cleaned_up { - return; - } - self.cleaned_up = true; - let stdin = std::io::stdin().as_raw_fd(); - let _ = nix::sys::termios::tcsetattr( - stdin, - nix::sys::termios::SetArg::TCSANOW, - &self.termios, - ); - } -} - -impl Drop for RawGuard { - fn drop(&mut self) { - self.cleanup(); - } -} pub struct Input { buf: Vec, @@ -120,24 +13,8 @@ pub struct Input { #[allow(clippy::new_without_default)] impl Input { - pub fn new() -> (Self, RawGuard) { - let stdin = std::io::stdin().as_raw_fd(); - let termios = nix::sys::termios::tcgetattr(stdin).unwrap(); - let mut termios_raw = termios.clone(); - nix::sys::termios::cfmakeraw(&mut termios_raw); - nix::sys::termios::tcsetattr( - stdin, - nix::sys::termios::SetArg::TCSANOW, - &termios_raw, - ) - .unwrap(); - ( - Self::new_without_raw(), - RawGuard { - termios, - cleaned_up: false, - }, - ) + pub fn new() -> (Self, crate::RawGuard) { + (Self::new_without_raw(), crate::RawGuard::new()) } pub fn new_without_raw() -> Self { @@ -172,7 +49,7 @@ impl Input { self.parse_single = parse; } - pub fn read_key(&mut self) -> std::io::Result> { + pub fn read_key(&mut self) -> std::io::Result> { if self.parse_single { self.read_single_key() } else { @@ -188,9 +65,11 @@ impl Input { if !prefix.is_empty() { self.pos += prefix.len(); match std::string::String::from_utf8(prefix) { - Ok(s) => return Ok(Some(Key::String(s))), + Ok(s) => return Ok(Some(crate::Key::String(s))), Err(e) => { - return Ok(Some(Key::Bytes(e.into_bytes()))) + return Ok(Some(crate::Key::Bytes( + e.into_bytes(), + ))) } } } @@ -213,12 +92,12 @@ impl Input { .collect(); if !prefix.is_empty() { self.pos += prefix.len(); - return Ok(Some(Key::Bytes(prefix))); + return Ok(Some(crate::Key::Bytes(prefix))); } self.read_single_key().map(|key| { - if let Some(Key::Byte(c)) = key { - Some(Key::Bytes(vec![c])) + if let Some(crate::Key::Byte(c)) = key { + Some(crate::Key::Bytes(vec![c])) } else { key } @@ -226,50 +105,52 @@ impl Input { } } - fn read_single_key(&mut self) -> std::io::Result> { + fn read_single_key(&mut self) -> std::io::Result> { match self.getc(true)? { - Some(0) => Ok(Some(Key::Byte(0))), + Some(0) => Ok(Some(crate::Key::Byte(0))), Some(c @ 1..=26) => { if self.parse_ctrl { - Ok(Some(Key::Ctrl(b'a' + c - 1))) + Ok(Some(crate::Key::Ctrl(b'a' + c - 1))) } else { - Ok(Some(Key::Byte(c))) + Ok(Some(crate::Key::Byte(c))) } } Some(27) => { if self.parse_meta || self.parse_special_keys { self.read_escape_sequence() } else { - Ok(Some(Key::Byte(27))) + Ok(Some(crate::Key::Byte(27))) } } - Some(c @ 28..=31) => Ok(Some(Key::Byte(c))), + Some(c @ 28..=31) => Ok(Some(crate::Key::Byte(c))), Some(c @ 32..=126) => { if self.parse_utf8 { - Ok(Some(Key::Char(c as char))) + Ok(Some(crate::Key::Char(c as char))) } else { - Ok(Some(Key::Byte(c))) + Ok(Some(crate::Key::Byte(c))) } } Some(127) => { if self.parse_special_keys { - Ok(Some(Key::Backspace)) + Ok(Some(crate::Key::Backspace)) } else { - Ok(Some(Key::Byte(127))) + Ok(Some(crate::Key::Byte(127))) } } Some(c @ 128..=255) => { if self.parse_utf8 { self.read_utf8_char(c) } else { - Ok(Some(Key::Byte(c))) + Ok(Some(crate::Key::Byte(c))) } } None => Ok(None), } } - fn read_escape_sequence(&mut self) -> std::io::Result> { + fn read_escape_sequence( + &mut self, + ) -> std::io::Result> { let mut seen = vec![b'\x1b']; macro_rules! fail { @@ -278,9 +159,9 @@ impl Input { self.ungetc(c); } if self.parse_special_keys { - return Ok(Some(Key::Escape)); + return Ok(Some(crate::Key::Escape)); } else { - return Ok(Some(Key::Byte(27))); + return Ok(Some(crate::Key::Byte(27))); } }}; } @@ -323,7 +204,7 @@ impl Input { } b' '..=b'N' | b'P'..=b'Z' | b'\\'..=b'~' => { if self.parse_meta { - return Ok(Some(Key::Meta(c))); + return Ok(Some(crate::Key::Meta(c))); } else { fail!() } @@ -331,47 +212,47 @@ impl Input { _ => fail!(), }, EscapeState::CSI(ref mut param) => match c { - b'A' => return Ok(Some(Key::Up)), - b'B' => return Ok(Some(Key::Down)), - b'C' => return Ok(Some(Key::Right)), - b'D' => return Ok(Some(Key::Left)), - b'H' => return Ok(Some(Key::Home)), - b'F' => return Ok(Some(Key::End)), + b'A' => return Ok(Some(crate::Key::Up)), + b'B' => return Ok(Some(crate::Key::Down)), + b'C' => return Ok(Some(crate::Key::Right)), + b'D' => return Ok(Some(crate::Key::Left)), + b'H' => return Ok(Some(crate::Key::Home)), + b'F' => return Ok(Some(crate::Key::End)), b'0'..=b'9' => param.push(c), b'~' => match param.as_slice() { - [b'2'] => return Ok(Some(Key::Insert)), - [b'3'] => return Ok(Some(Key::Delete)), - [b'5'] => return Ok(Some(Key::PageUp)), - [b'6'] => return Ok(Some(Key::PageDown)), - [b'1', b'5'] => return Ok(Some(Key::F(5))), - [b'1', b'7'] => return Ok(Some(Key::F(6))), - [b'1', b'8'] => return Ok(Some(Key::F(7))), - [b'1', b'9'] => return Ok(Some(Key::F(8))), - [b'2', b'0'] => return Ok(Some(Key::F(9))), - [b'2', b'1'] => return Ok(Some(Key::F(10))), - [b'2', b'3'] => return Ok(Some(Key::F(11))), - [b'2', b'4'] => return Ok(Some(Key::F(12))), - [b'2', b'5'] => return Ok(Some(Key::F(13))), - [b'2', b'6'] => return Ok(Some(Key::F(14))), - [b'2', b'8'] => return Ok(Some(Key::F(15))), - [b'2', b'9'] => return Ok(Some(Key::F(16))), - [b'3', b'1'] => return Ok(Some(Key::F(17))), - [b'3', b'2'] => return Ok(Some(Key::F(18))), - [b'3', b'3'] => return Ok(Some(Key::F(19))), - [b'3', b'4'] => return Ok(Some(Key::F(20))), + [b'2'] => return Ok(Some(crate::Key::Insert)), + [b'3'] => return Ok(Some(crate::Key::Delete)), + [b'5'] => return Ok(Some(crate::Key::PageUp)), + [b'6'] => return Ok(Some(crate::Key::PageDown)), + [b'1', b'5'] => return Ok(Some(crate::Key::F(5))), + [b'1', b'7'] => return Ok(Some(crate::Key::F(6))), + [b'1', b'8'] => return Ok(Some(crate::Key::F(7))), + [b'1', b'9'] => return Ok(Some(crate::Key::F(8))), + [b'2', b'0'] => return Ok(Some(crate::Key::F(9))), + [b'2', b'1'] => return Ok(Some(crate::Key::F(10))), + [b'2', b'3'] => return Ok(Some(crate::Key::F(11))), + [b'2', b'4'] => return Ok(Some(crate::Key::F(12))), + [b'2', b'5'] => return Ok(Some(crate::Key::F(13))), + [b'2', b'6'] => return Ok(Some(crate::Key::F(14))), + [b'2', b'8'] => return Ok(Some(crate::Key::F(15))), + [b'2', b'9'] => return Ok(Some(crate::Key::F(16))), + [b'3', b'1'] => return Ok(Some(crate::Key::F(17))), + [b'3', b'2'] => return Ok(Some(crate::Key::F(18))), + [b'3', b'3'] => return Ok(Some(crate::Key::F(19))), + [b'3', b'4'] => return Ok(Some(crate::Key::F(20))), _ => fail!(), }, _ => fail!(), }, EscapeState::CKM => match c { - b'A' => return Ok(Some(Key::KeypadUp)), - b'B' => return Ok(Some(Key::KeypadDown)), - b'C' => return Ok(Some(Key::KeypadRight)), - b'D' => return Ok(Some(Key::KeypadLeft)), - b'P' => return Ok(Some(Key::F(1))), - b'Q' => return Ok(Some(Key::F(2))), - b'R' => return Ok(Some(Key::F(3))), - b'S' => return Ok(Some(Key::F(4))), + b'A' => return Ok(Some(crate::Key::KeypadUp)), + b'B' => return Ok(Some(crate::Key::KeypadDown)), + b'C' => return Ok(Some(crate::Key::KeypadRight)), + b'D' => return Ok(Some(crate::Key::KeypadLeft)), + b'P' => return Ok(Some(crate::Key::F(1))), + b'Q' => return Ok(Some(crate::Key::F(2))), + b'R' => return Ok(Some(crate::Key::F(3))), + b'S' => return Ok(Some(crate::Key::F(4))), _ => fail!(), }, } @@ -381,7 +262,7 @@ impl Input { fn read_utf8_char( &mut self, initial: u8, - ) -> std::io::Result> { + ) -> std::io::Result> { let mut buf = vec![initial]; macro_rules! fail { @@ -389,7 +270,7 @@ impl Input { for &c in buf.iter().skip(1).rev() { self.ungetc(c); } - return Ok(Some(Key::Byte(initial))); + return Ok(Some(crate::Key::Byte(initial))); }}; } macro_rules! next_byte { @@ -425,7 +306,7 @@ impl Input { } match std::string::String::from_utf8(buf) { - Ok(s) => Ok(Some(Key::Char(s.chars().next().unwrap()))), + Ok(s) => Ok(Some(crate::Key::Char(s.chars().next().unwrap()))), Err(e) => { buf = e.into_bytes(); fail!() diff --git a/src/blocking/mod.rs b/src/blocking/mod.rs index d4ffe4a..919b08f 100644 --- a/src/blocking/mod.rs +++ b/src/blocking/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod input; -pub use input::{Input, RawGuard}; +pub use crate::RawGuard; +pub use input::Input; mod output; pub use output::{Output, ScreenGuard}; -- cgit v1.2.3-54-g00ecf