cleaning up

parse-tree
Jordan Orelli 2 years ago
parent 79e41a376a
commit 755e16d045

@ -1,7 +1,7 @@
use crate::{error::Error, key, log::*};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use crate::{error::Error, log::*, key};
use windows::Win32::System::Console;
use windows::Win32::Foundation::HANDLE; use windows::Win32::Foundation::HANDLE;
use windows::Win32::System::Console;
fn log_input_mode(mode: Console::CONSOLE_MODE) { fn log_input_mode(mode: Console::CONSOLE_MODE) {
// Characters read by the ReadFile or ReadConsole function are written to the active screen // Characters read by the ReadFile or ReadConsole function are written to the active screen
@ -149,7 +149,11 @@ impl Reader {
// All buffered items have been processed, ask the OS for new event records // All buffered items have been processed, ask the OS for new event records
if self.buf_idx as u32 >= self.buf_len { if self.buf_idx as u32 >= self.buf_len {
unsafe { unsafe {
Error::check(Console::ReadConsoleInputA(self.input, &mut self.buf, &mut self.buf_len))?; Error::check(Console::ReadConsoleInputA(
self.input,
&mut self.buf,
&mut self.buf_len,
))?;
} }
self.buf_idx = 0; self.buf_idx = 0;
} }
@ -163,9 +167,12 @@ impl Reader {
#[derive(Debug)] #[derive(Debug)]
pub enum Event { pub enum Event {
Focus(bool), Focus(bool),
Menu, Menu(u32),
Key(key::Event), Key(key::Event),
Mouse, Mouse{
x: i16,
y: i16,
},
Size, Size,
} }
@ -178,52 +185,52 @@ impl From<Console::INPUT_RECORD> for Event {
// This is documented here: // This is documented here:
// https://learn.microsoft.com/en-us/windows/console/input-record-str // https://learn.microsoft.com/en-us/windows/console/input-record-str
match rec.EventType as u32 { match rec.EventType as u32 {
Console::FOCUS_EVENT => { Console::FOCUS_EVENT => unsafe {
unsafe {
let event = rec.Event.FocusEvent; let event = rec.Event.FocusEvent;
Event::Focus(event.bSetFocus.as_bool()) Event::Focus(event.bSetFocus.as_bool())
} },
} Console::MENU_EVENT => unsafe {
Console::MENU_EVENT => {
// The Event member contains a MENU_EVENT_RECORD structure. These events are
// used internally and should be ignored.
unsafe {
let event = rec.Event.MenuEvent; let event = rec.Event.MenuEvent;
debug!("Menu Event: {:?}", event); Event::Menu(event.dwCommandId)
} },
Event::Menu
}
Console::KEY_EVENT => { Console::KEY_EVENT => {
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes // https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
unsafe { unsafe {
let event = rec.Event.KeyEvent; let event = rec.Event.KeyEvent;
// pub struct KEY_EVENT_RECORD {
// pub bKeyDown: super::super::Foundation::BOOL,
// pub wRepeatCount: u16,
// pub wVirtualKeyCode: u16,
// pub wVirtualScanCode: u16,
// pub uChar: KEY_EVENT_RECORD_0,
// pub dwControlKeyState: u32,
// }
let mstate = event.dwControlKeyState; let mstate = event.dwControlKeyState;
let c = char::from_u32(event.uChar.UnicodeChar as u32).unwrap_or('💀');
Event::Key(key::Event{ Event::Key(key::Event {
down: event.bKeyDown.as_bool(), down: event.bKeyDown.as_bool(),
repeats: event.wRepeatCount, repeats: event.wRepeatCount,
code: event.wVirtualKeyCode, code: event.wVirtualKeyCode,
alt: mstate & ALT_KEYS > 0, alt: mstate & ALT_KEYS > 0,
ctrl: mstate & CTRL_KEYS > 0, ctrl: mstate & CTRL_KEYS > 0,
shift: mstate & SHIFT_PRESSED > 0, shift: mstate & SHIFT_PRESSED > 0,
char: c,
}) })
} }
} }
Console::MOUSE_EVENT => { Console::MOUSE_EVENT => {
Event::Mouse // OK I think it's safe to ignore these events since we're using the terminal
// escape sequences. I think we never see them because terminal.exe is going to
// turn mouse events into virtual terminal sequences anyway
unsafe {
let event = rec.Event.MouseEvent;
// pub dwMousePosition: COORD, i16 i16
// pub dwButtonState: u32,
// pub dwControlKeyState: u32,
// pub dwEventFlags: u32,
Event::Mouse{
x: event.dwMousePosition.X,
y: event.dwMousePosition.Y,
}
}
} }
Console::WINDOW_BUFFER_SIZE_EVENT => { Console::WINDOW_BUFFER_SIZE_EVENT => Event::Size,
Event::Size _ => {
unreachable!()
} }
_ => { unreachable!() }
} }
} }
} }

@ -2,14 +2,70 @@ type Code = u16;
#[derive(Debug)] #[derive(Debug)]
pub struct Event { pub struct Event {
/// True for key press events, false for key release events
pub down: bool, pub down: bool,
/// The number of times this event has happened in sequence
pub repeats: u16, pub repeats: u16,
/// The virtual key code for the keyboard event
pub code: Code, pub code: Code,
pub alt: bool,
/// The unicode character, or 💀 if not applicable
pub char: char,
/// Whether or not one of the CTRL keys was held when the event was triggered
pub ctrl: bool, pub ctrl: bool,
/// Whether or not one of the ALT keys was held when the event was triggered
pub alt: bool,
/// Whether or not one of the SHIFT keys was held when the event was triggered
pub shift: bool, pub shift: bool,
} }
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, "<S-C-A-{}>", self.char)
} else {
// write!(f, "⇧⎈ {}", self.char)
write!(f, "<S-C-{}>", self.char)
}
} else {
if self.alt {
// write!(f, "⇧⎇ {}", self.char)
write!(f, "<S-A-{}>", self.char)
} else {
write!(f, "<S-{}>", self.char)
}
}
} else {
if self.ctrl {
if self.alt {
// write!(f, "⎈⎇ {}", self.char)
write!(f, "<C-A-{}>", self.char)
} else {
// write!(f, "⎈ {}", self.char)
write!(f, "<C-{}>", self.char)
}
} else {
if self.alt {
// write!(f, "⎇ {}", self.char)
write!(f, "<A-{}>", self.char)
} else {
write!(f, "{}", self.char)
}
}
}
}
}
macro_rules! keycodes { macro_rules! keycodes {
($($c:literal $n:ident $x:literal)*) => {$( ($($c:literal $n:ident $x:literal)*) => {$(
#[allow(dead_code)] #[allow(dead_code)]
@ -17,7 +73,7 @@ macro_rules! keycodes {
)*}; )*};
} }
keycodes!{ keycodes! {
0x08 BACKSPACE '⌫' 0x08 BACKSPACE '⌫'
0x09 TAB '↹' 0x09 TAB '↹'
// 0x0A-0B Reserved // 0x0A-0B Reserved

@ -1,9 +1,9 @@
mod error; mod error;
mod input;
mod key;
mod line; mod line;
mod log; mod log;
mod input;
mod prompt; mod prompt;
mod key;
use line::Line; use line::Line;
use prompt::Prompt; use prompt::Prompt;
@ -129,6 +129,18 @@ fn setup_stdout() -> Result<()> {
Ok(()) Ok(())
} }
fn newline(stdout: HANDLE) -> Result<()> {
unsafe {
Error::check(Console::WriteConsoleA(
stdout,
"\r\n".as_bytes(),
None,
None,
))?;
}
Ok(())
}
fn main() -> Result<()> { fn main() -> Result<()> {
match Log::file("C:\\Users\\JordanOrelli\\wash.log") { match Log::file("C:\\Users\\JordanOrelli\\wash.log") {
Ok(f) => { Ok(f) => {
@ -151,95 +163,43 @@ fn main() -> Result<()> {
loop { loop {
let rec = input.next()?; let rec = input.next()?;
let event: input::Event = rec.into(); let event: input::Event = rec.into();
debug!("Event Type: {}", rec.EventType); match event {
if let input::Event::Key(event) = &event { input::Event::Key(event) => {
debug!("Key Event: {:?}", event); if event.down {
if event.code == key::ENTER { continue;
debug!("ENTER!!!");
} }
} debug!("Key Event: {}", event);
match rec.EventType as u32 {
Console::FOCUS_EVENT => { if event.code == key::ENTER {
// The Event member contains a FOCUS_EVENT_RECORD structure. These events are newline(stdout)?;
// used internally and should be ignored.
unsafe {
let event = rec.Event.FocusEvent;
debug!("Focus Event: {:?}", event);
}
}
Console::MENU_EVENT => {
// The Event member contains a MENU_EVENT_RECORD structure. These events are
// used internally and should be ignored.
unsafe {
let event = rec.Event.MenuEvent;
debug!("Menu Event: {:?}", event);
}
}
Console::KEY_EVENT => {
// The Event member contains a KEY_EVENT_RECORD structure with information
// about a keyboard event.
unsafe {
let event = rec.Event.KeyEvent;
let down = event.bKeyDown.as_bool();
let repeats = event.wRepeatCount;
let key_code = event.wVirtualKeyCode;
let scan_code = event.wVirtualScanCode;
let c = event.uChar.UnicodeChar;
let modifiers = event.dwControlKeyState;
// handle key presses on key up, not key down. This is a little weird but
// it's sending both down and up events when you hit the key anyway. I
// dunno if this is right. But for some reason, the down events don't have
// the modifiers
if !down {
// Carriage Return (Enter key)
if c == 13 {
let mask = Console::LEFT_ALT_PRESSED
| Console::RIGHT_ALT_PRESSED
| Console::LEFT_CTRL_PRESSED
| Console::RIGHT_CTRL_PRESSED
| Console::SHIFT_PRESSED;
if modifiers & mask == 0 {
Error::check(Console::WriteConsoleA(
stdout,
"\r\n".as_bytes(),
None,
None,
))?;
line.print()?; line.print()?;
Error::check(Console::WriteConsoleA( newline(stdout)?;
stdout,
"\r\n".as_bytes(),
None,
None,
))?;
prompt.print()?; prompt.print()?;
line.clear(); line.clear();
continue;
} }
} else if key_code == 68
&& (modifiers & Console::LEFT_CTRL_PRESSED if event.ctrl && event.code == key::D {
== Console::LEFT_CTRL_PRESSED) unsafe {
{
// this is CTRL+D
CloseHandle(stdout); CloseHandle(stdout);
}
return Ok(()); return Ok(());
} else if key_code == 74 }
&& (modifiers & Console::LEFT_CTRL_PRESSED
== Console::LEFT_CTRL_PRESSED) if event.ctrl && event.code == key::J {
{
// red bullet // red bullet
unsafe {
let text = "\x1b[31m\u{2022}\x1b[0m"; let text = "\x1b[31m\u{2022}\x1b[0m";
Error::check(Console::WriteConsoleA( Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
stdout, }
text.as_bytes(), continue;
None, }
None,
))?; if !event.char.is_control() {
} else {
if let Some(c) = char::from_u32(event.uChar.UnicodeChar as u32) {
if !c.is_control() {
let mut buf = [0 as u8; 8]; let mut buf = [0 as u8; 8];
let s = c.encode_utf8(&mut buf); let s = event.char.encode_utf8(&mut buf);
s.chars().for_each(|c| line.append(c)); s.chars().for_each(|c| line.append(c));
unsafe {
Error::check(Console::WriteConsoleW( Error::check(Console::WriteConsoleW(
stdout, stdout,
s.as_bytes(), s.as_bytes(),
@ -247,31 +207,14 @@ fn main() -> Result<()> {
None, None,
))?; ))?;
} }
continue;
} }
} }
} input::Event::Focus(true) => {},
debug!( input::Event::Focus(false) => {},
"Key Event: down: {down:?} repeats: {repeats} key-code: {key_code} scan-code: {scan_code} char: {c} modifiers: {modifiers}" input::Event::Menu(_command_id) => {},
); input::Event::Mouse{..} => {},
} input::Event::Size => {},
}
Console::MOUSE_EVENT => {
// The Event member contains a MOUSE_EVENT_RECORD structure with information
// about a mouse movement or button press event.
unsafe {
let event = rec.Event.MouseEvent;
debug!("Mouse Event: {:?}", event);
}
}
Console::WINDOW_BUFFER_SIZE_EVENT => {
// The Event member contains a WINDOW_BUFFER_SIZE_RECORD structure with
// information about the new size of the console screen buffer.
unsafe {
let event = rec.Event.WindowBufferSizeEvent;
debug!("Window Buffer Event: {:?}", event);
}
}
_ => {}
} }
} }
} }

Loading…
Cancel
Save