small software-rendered rust tty
-rw-r--r--.gitignore3
-rw-r--r--pattypan.terminfo2
-rw-r--r--src/keyboard.rs148
-rw-r--r--src/main.rs75
4 files changed, 157 insertions, 71 deletions
diff --git a/.gitignore b/.gitignore
index a1922f9..5fd7d41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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();
}
});