small software-rendered rust tty
add a keyboard module
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | pattypan.terminfo | 2 | ||||
| -rw-r--r-- | src/keyboard.rs | 148 | ||||
| -rw-r--r-- | src/main.rs | 75 |
4 files changed, 157 insertions, 71 deletions
@@ -1,2 +1,3 @@ Cargo.lock -x
\ No newline at end of file +x +rustc-ice-*
\ No newline at end of file diff --git a/pattypan.terminfo b/pattypan.terminfo index 1c9f25f..00cfcaf 100644 --- a/pattypan.terminfo +++ b/pattypan.terminfo @@ -66,6 +66,8 @@ pattypan|patty, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, + kLFT=\E[1;2D, + kRIT=\E[1;2C, kdch1=\E[3~, kend=\EOF, kf1=\EOP, diff --git a/src/keyboard.rs b/src/keyboard.rs new file mode 100644 index 0000000..de15ed4 --- /dev/null +++ b/src/keyboard.rs @@ -0,0 +1,148 @@ +use atools::prelude::*; +use minifb::Key; +#[derive(Clone, Copy)] +pub struct Modifiers { + shift: bool, + alt: bool, + ctrl: bool, +} + +impl Modifiers { + #[implicit_fn::implicit_fn] + fn x(self) -> u8 { + [self.shift, self.alt, self.ctrl] + .iter() + .zip(0..) + .filter(*_.0) + .fold(0u8, |acc, x| acc | 1 << x.1) + } +} + +pub struct Board { + mods: Modifiers, +} +impl Board { + pub fn new() -> Self { + Self { + mods: Modifiers { + alt: false, + shift: false, + ctrl: false, + }, + } + } + + pub fn rx(&mut self, k: Key, s: bool) -> Vec<u8> { + use Key::*; + let Self { + mods: Modifiers { shift, ctrl, alt }, + } = self; + if !s { + if k == LeftAlt || k == RightAlt { + *alt = false; + } + if k == LeftShift || k == RightShift { + *shift = false; + } + if k == LeftCtrl || k == RightCtrl { + *ctrl = false; + } + return vec![]; + } + + let l = match k as u8 { + k @ 10..=34 if *shift => Some(k - 10 + b'A'), + k @ 10..=34 => Some(k - 10 + b'a'), + _ => None, + } + .map(char::from); + let mut v = vec![]; + match k { + LeftSuper | RightSuper => {} + LeftAlt | RightAlt => { + *alt = true; + } + LeftShift | RightShift => { + *shift = true; + } + LeftCtrl | RightCtrl => { + *ctrl = true; + } + k if let Some(l) = l + && *ctrl => + { + let k = l.to_ascii_uppercase() as u8 & 0x1f; + if *alt { + v.push(0x1b); + } + v.push(k); + } + _ if let Some(l) = l + && *alt => + { + v.extend([0x1b, l as u8]); + } + Enter => v.extend(b"\n"), + Delete => v.extend(b"\x1b[3~"), + Insert => v.extend(b"\x1b[2~"), + Escape => v.extend(b"\x1b"), + Up | Down | Left | Right | Home | End | NumPad7 | NumPad1 => { + let c = match k { + Up => b'A', + Down => b'B', + Right => b'C', + Left => b'D', + Home | NumPad7 => b'H', + End | NumPad1 => b'F', + _ => unreachable!(), + }; + if *shift | *alt | *ctrl { + v.extend( + (*b"\x1b[1;") + .join(1 + self.mods.x() + b'0') + .join(c), + ); + } else { + v.extend((*b"\x1b[").join(c)); + } + } + Apostrophe if *shift => v.extend(b"\""), + Apostrophe => v.extend(b"'"), + Space => v.extend(b" "), + Period => v.extend(b"."), + Slash if *shift => v.extend(b"?"), + Slash => v.extend(b"/"), + Backslash if *shift => v.extend(b"|"), + Backslash => v.extend(b"\\"), + Backspace => v.extend(b""), + Equal if *shift => v.extend(b"+"), + Equal => v.extend(b"="), + Tab => v.extend(b"\t"), + Minus if *shift => v.extend(b"_"), + Minus => v.extend(b"-"), + LeftBracket if *shift => v.extend(b"{"), + LeftBracket => v.extend(b"["), + RightBracket => v.extend(b"]"), + Semicolon if *shift => v.extend(b":"), + Semicolon => v.extend(b";"), + Comma => v.extend(b","), + Backquote if *shift => v.extend(b"~"), + Backquote => v.extend(b"`"), + + Key0 | Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 + | Key8 | Key9 + if *shift => + { + v.push(b")!@#$%^&*("[k as usize]); + } + + Key0 | Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 + | Key8 | Key9 => v.push(k as u8 + b'0'), + + _ if *ctrl => v.push(k as u8 - 9), + _ if *shift => v.push(k as u8 - 10 + b'A'), + _ => v.push(k as u8 - 10 + b'a'), + }; + v + } +} diff --git a/src/main.rs b/src/main.rs index 4c46531..c5fdb5f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ deadline_api, deref_patterns, generic_const_exprs, + guard_patterns, impl_trait_in_bindings, if_let_guard, import_trait_associated_functions @@ -20,6 +21,7 @@ use std::thread::sleep; use std::time::{Duration, Instant}; pub mod colors; +mod keyboard; use anyhow::Result; use fimg::Image; @@ -102,77 +104,10 @@ fn main() -> Result<()> { let pty2 = pty.try_clone()?; std::thread::spawn(move || { - use Key::*; - let mut shifting = false; - let mut ctrl = false; + let mut b = keyboard::Board::new(); while let Ok((k, s)) = krx.recv() { - if !s { - if k == LeftShift || k == RightShift { - shifting = false; - } - if k == LeftCtrl || k == RightCtrl { - ctrl = false; - } - continue; - } - - let x = match k { - LeftSuper | RightSuper => continue, - LeftShift | RightShift => { - shifting = true; - continue; - } - LeftCtrl | RightCtrl => { - ctrl = true; - continue; - } - Enter => &b"\n"[..], - Delete => b"\x1b[3~", - Insert => b"\x1b[2~", - Escape => b"\x1b", - Up => b"\x1b[A", - Down => b"\x1b[B", - Right => b"\x1b[C", - Left => b"\x1b[D", - NumPad7 | Home => b"\x1b[H", - NumPad1 | End => b"\x1b[F", - Apostrophe if shifting => b"\"", - Apostrophe => b"'", - Space => b" ", - Period => b".", - Slash if shifting => b"?", - Slash => b"/", - Backslash if shifting => b"|", - Backslash => b"\\", - Backspace => b"", - Equal if shifting => b"+", - Equal => b"=", - Tab => b"\t", - Minus if shifting => b"_", - Minus => b"-", - LeftBracket if shifting => b"{", - LeftBracket => b"[", - RightBracket => b"]", - Semicolon if shifting => b":", - Semicolon => b";", - Comma => b",", - Backquote if shifting => b"~", - Backquote => b"`", - - Key0 | Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 - | Key8 | Key9 - if shifting => - { - &[b")!@#$%^&*("[k as usize]] - } - - Key0 | Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 - | Key8 | Key9 => &[k as u8 + b'0'], - _ if ctrl => &[k as u8 - 9], - _ if shifting => &[k as u8 - 10 + b'A'], - _ => &[k as u8 - 10 + b'a'], - }; - write(pty1.as_fd(), x).unwrap(); + let x = b.rx(k, s); + write(pty1.as_fd(), &x).unwrap(); } }); |