diff --git a/src/input.rs b/src/input.rs index 65c82d6..1508130 100644 --- a/src/input.rs +++ b/src/input.rs @@ -178,8 +178,12 @@ impl Reader { fn next_escape_sequence(&mut self) -> Result { self.take_bracket()?; match self.next_escape_char()? { - 'D' => Ok(Event::Left), + 'A' => Ok(Event::Up), + 'B' => Ok(Event::Down), 'C' => Ok(Event::Right), + 'D' => Ok(Event::Left), + 'H' => Ok(Event::Home), + 'F' => Ok(Event::End), e => Err(Error::input_error(format!("unexpected escape char: {}", e)).into()), } } @@ -229,6 +233,10 @@ pub enum Event { Size, Left, Right, + Up, + Down, + Home, + End, } const ALT_KEYS: u32 = 0x0002 | 0x0001; @@ -255,10 +263,15 @@ impl From for Event { let mstate = event.dwControlKeyState; let c = char::from_u32(event.uChar.UnicodeChar as u32).unwrap_or('๐Ÿ’€'); + if event.bKeyDown.as_bool() { + debug!("key down {}", event.wVirtualKeyCode); + } else { + debug!("key up {}", event.wVirtualKeyCode); + } Event::Key(key::Event { down: event.bKeyDown.as_bool(), repeats: event.wRepeatCount, - code: event.wVirtualKeyCode, + code: key::CODES[event.wVirtualKeyCode as usize], alt: mstate & ALT_KEYS > 0, ctrl: mstate & CTRL_KEYS > 0, shift: mstate & SHIFT_PRESSED > 0, diff --git a/src/key.rs b/src/key.rs index 4c617a6..a34df14 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1,4 +1,13 @@ -type Code = u16; +// type Code = u16; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct Code { + /// The integer value of the keycode + pub val: u16, + + /// The unicode symbol that represents the keycode, if any + pub sym: Option, +} #[derive(Debug)] pub struct Event { @@ -26,54 +35,35 @@ pub struct Event { impl Event {} -impl std::fmt::Display for Event { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.shift { - if self.ctrl { - if self.alt { - // write!(f, "โ‡งโŽˆโŽ‡ {}", self.char) - write!(f, "", self.char) - } else { - // write!(f, "โ‡งโŽˆ {}", self.char) - write!(f, "", self.char) - } - } else { - if self.alt { - // write!(f, "โ‡งโŽ‡ {}", self.char) - write!(f, "", self.char) - } else { - write!(f, "", self.char) - } - } - } else { - if self.ctrl { - if self.alt { - // write!(f, "โŽˆโŽ‡ {}", self.char) - write!(f, "", self.char) - } else { - // write!(f, "โŽˆ {}", self.char) - write!(f, "", self.char) - } - } else { - if self.alt { - // write!(f, "โŽ‡ {}", self.char) - write!(f, "", self.char) - } else { - write!(f, "{}", self.char) - } +/// CODES contains a lookup table for key codes. Note that this is a sparse array and not all +/// values associate to valid key codes. +pub static CODES: [Code; 256] = gen_codes(); + +macro_rules! keycodes { + ($($val:literal $name:ident $sym:literal)*) => { + const fn gen_codes() -> [Code; 256] { + let mut codes = [Code{val: 0, sym: None}; 256]; + let mut i = 0 as usize; + while i < 256 { + codes[i] = Code{val: i as u16, sym: None}; + i = i + 1; } + + $( + codes[$val] = Code{val: $val, sym: Some($sym)}; + )* + codes } - } -} -macro_rules! keycodes { - ($($c:literal $n:ident $x:literal)*) => {$( - #[allow(dead_code)] - pub const $n: Code = $c; - )*}; + $( + #[allow(dead_code)] + pub const $name: Code = Code{val: $val, sym: Some($sym)}; + )* + } } keycodes! { + 0x07 NOTBACKSPACE 'โŒซ' 0x08 BACKSPACE 'โŒซ' 0x09 TAB 'โ†น' // 0x0A-0B Reserved diff --git a/src/line.rs b/src/line.rs index 8dbc359..21eeba2 100644 --- a/src/line.rs +++ b/src/line.rs @@ -37,7 +37,7 @@ impl Line { Ok(()) } - pub fn back(&mut self) -> bool{ + pub fn back(&mut self) -> bool { if self.cursor > 0 { self.cursor -= 1; true @@ -46,6 +46,16 @@ impl Line { } } + pub fn backspace(&mut self) -> bool { + if self.cursor > 0 { + self.cursor -= 1; + self.chars.remove(self.cursor); + true + } else { + false + } + } + pub fn forward(&mut self) -> bool { if self.cursor < self.chars.len() { self.cursor += 1; diff --git a/src/main.rs b/src/main.rs index 546d258..decbcdb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -163,7 +163,6 @@ fn main() -> Result<()> { loop { match input.next()? { input::Event::Key(event) => { - debug!("Key Event: {}", event); if event.down { continue; } @@ -177,6 +176,34 @@ fn main() -> Result<()> { continue; } + if event.code == key::TAB { + continue; + } + + if event.code == key::BACKSPACE { + if line.backspace() { + let text = format!("\x1b[2D"); + unsafe { + Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?; + } + let tail = format!("{} ", line.tail()); + let n = tail.chars().count(); + unsafe { + Error::check(Console::WriteConsoleA( + stdout, + tail.as_bytes(), + None, + None, + ))?; + } + let text = format!("\x1b[1D"); + unsafe { + Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?; + } + } + continue; + } + if event.ctrl && event.code == key::D { unsafe { CloseHandle(stdout); @@ -185,8 +212,8 @@ fn main() -> Result<()> { } if event.ctrl && event.code == key::J { - // red bullet unsafe { + // red bullet let text = "\x1b[31m\u{2022}\x1b[0m"; Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?; } @@ -220,7 +247,7 @@ fn main() -> Result<()> { continue; } - debug!("Unhandled Keyboard Event: {}", event); + debug!("Unhandled Keyboard Event: {:?}", event.code); } input::Event::Left => { if line.back() { @@ -238,6 +265,10 @@ fn main() -> Result<()> { } } } + input::Event::Up => {}, + input::Event::Down => {}, + input::Event::Home => {}, + input::Event::End => {}, input::Event::Focus(true) => {}, input::Event::Focus(false) => {}, input::Event::Menu(_command_id) => {},