From 544bedbd452d6e9448b414aac9be4bfaa8df0d3b Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sun, 30 Sep 2018 09:02:37 +0200 Subject: parser: Add `key_code` and `special_key` parsers Still need to test them though. They'll be used in conjunction with another new parser, `action_map`, which will parser map-type action strings. `key_code` parses `autopilot::key::KeyCode`s, basically all special keys and modifiers. `special_key` parses key codes inside `<` `>` braces. Change the test to use `easy_parse` to give a clear error message. Add `recursion_limit` to the crate on the advice of the compiler in order for the `choice!` macro in `key_code()` to work properly. Otherwise it spits out a giant error message complaining about `rustc --explain E0277`. If I remove a handful of elements from the `choice!`, it compiles, so it seems there's an upper bound restricted by the recursion limit. Modifier keys are included in a commented section as these are part of the 'autopilot' `KeyCode` enum, but they'll be handled in a separate parser. --- src/lib.rs | 2 ++ src/parser.rs | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index b51b165..c6f66d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit="128"] + extern crate autopilot; // extern crate cocoa; diff --git a/src/parser.rs b/src/parser.rs index 21132b1..2e100df 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -142,6 +142,16 @@ impl MapGroup { } +fn string_case_insensitive( + s: &'static str +) -> impl Parser +where + I: Stream, + I::Error: ParseError, +{ + string_cmp(s, |l, r| l.eq_ignore_ascii_case(&r)) +} + fn map_kind() -> impl Parser where I: Stream, @@ -189,6 +199,106 @@ where .map(|action| Action::String(action)) } +fn action_map() -> impl Parser +where + I: Stream, + I::Error: ParseError, +{ + take_until(newline()) + .map(|action| Action::String(action)) +} + +fn special_key() -> impl Parser +where + I: Stream, + I::Error: ParseError, +{ + between(token('<'), token('>'), key_code()) + .map(|code| + KeyboardKeyWithModifiers::new( + KeyboardKey::KeyCode(code), + None, + ) + ) +} + +fn key_code() -> impl Parser +where + I: Stream, + I::Error: ParseError, +{ + choice!( + string_case_insensitive("F1") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F1)), + string_case_insensitive("F2") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F2)), + string_case_insensitive("F3") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F3)), + string_case_insensitive("F4") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F4)), + string_case_insensitive("F5") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F5)), + string_case_insensitive("F6") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F6)), + string_case_insensitive("F7") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F7)), + string_case_insensitive("F8") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F8)), + string_case_insensitive("F9") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F9)), + string_case_insensitive("F10") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F10)), + string_case_insensitive("F11") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F11)), + string_case_insensitive("F12") + .map(|_| KeyCode::new(autopilot::key::KeyCode::F12)), + string_case_insensitive("Left") + .map(|_| KeyCode::new(autopilot::key::KeyCode::LeftArrow)), + string_case_insensitive("Right") + .map(|_| KeyCode::new(autopilot::key::KeyCode::RightArrow)), + string_case_insensitive("Down") + .map(|_| KeyCode::new(autopilot::key::KeyCode::DownArrow)), + string_case_insensitive("Up") + .map(|_| KeyCode::new(autopilot::key::KeyCode::UpArrow)), + string_case_insensitive("Home") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Home)), + string_case_insensitive("End") + .map(|_| KeyCode::new(autopilot::key::KeyCode::End)), + string_case_insensitive("PageUp") + .map(|_| KeyCode::new(autopilot::key::KeyCode::PageUp)), + string_case_insensitive("PageDown") + .map(|_| KeyCode::new(autopilot::key::KeyCode::PageDown)), + string_case_insensitive("Return") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Return)), + string_case_insensitive("Enter") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Return)), + string_case_insensitive("CR") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Return)), + string_case_insensitive("Del") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Delete)), + string_case_insensitive("BS") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Backspace)), + string_case_insensitive("Esc") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Escape)), + string_case_insensitive("CapsLock") + .map(|_| KeyCode::new(autopilot::key::KeyCode::CapsLock)), + string_case_insensitive("Tab") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Tab)), + string_case_insensitive("Space") + .map(|_| KeyCode::new(autopilot::key::KeyCode::Space)) + ) + // string_case_insensitive("Control") + // .map(|_| KeyCode::new(autopilot::key::KeyCode::Control)), + // string_case_insensitive("Alt") + // .map(|_| KeyCode::new(autopilot::key::KeyCode::Alt)), + // string_case_insensitive("Shift") + // .map(|_| KeyCode::new(autopilot::key::KeyCode::Shift)), + // string_case_insensitive("Meta") + // .map(|_| KeyCode::new(autopilot::key::KeyCode::Meta)), + // + // +} + fn whitespace_separator() -> impl Parser where I: Stream, @@ -453,7 +563,7 @@ mod tests { None, ), ]); - let result = action_map().parse(text).map(|t| t.0); + let result = action_map().easy_parse(text).map(|t| t.0); assert_eq!(result, Ok(expected)); } -- cgit v1.2.3