From dc606d756ceecf5ae8a52e607fd4a68727fd2529 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sun, 30 Sep 2018 20:43:27 +0200 Subject: special_key(): Handle modifier + character special keys Previously we were able to parse modifier + KeyCode (``) special keys and plain KeyCode ones (``). This change adds parsing support for the final type of special key, modifier + character (e.g. ``). action_character(): Move the `map` outside of this function and into `action_map()` to allow us to reuse the parsed `char` in `special_key()`. key_modifier(): * Move the `many()` parser and `Option` handling outside of this function and into `special_key()`. Doing so enables us to say: // Character special keys _require_ a modifier (thus // `many1`) <[C-]Left> // KeyCode special keys may or may not have a modifier // (thus `many`) * Rename from `key_modifiers()` to singular now that it only parses a single modifier. special_key(): Parse both character and KeyCode special keys with modifiers. action_parses_map_with_modifier(): Change input string to include a KeyCode-style special key with a modifier since we didn't have one previously. This ensures we test both kinds of special keys. --- src/parser.rs | 101 +++++++++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/parser.rs b/src/parser.rs index 0ccb05d..0389cf5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -207,14 +207,20 @@ where ( many( choice!( - action_character(), + action_character() + .map(|c| + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new(c)), + None, + ) + ), special_key() ) ), ).map(|(keys,)| Action::Map(keys)) } -fn action_character() -> impl Parser +fn action_character() -> impl Parser where I: Stream, I::Error: ParseError, @@ -223,12 +229,6 @@ where satisfy(|c| c != '<' && c != '\\'), action_escape() ) - .map(|c| - KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new(c)), - None, - ) - ) } fn action_escape() -> impl Parser @@ -247,40 +247,49 @@ where I: Stream, I::Error: ParseError, { - between(token('<'), token('>'), ( - key_modifiers(), - key_code() - )) - .map(|(modifiers, code)| - KeyboardKeyWithModifiers::new( - KeyboardKey::KeyCode(code), - modifiers, - ) + between( + token('<'), + token('>'), + or( + try(( + many(key_modifier()), + key_code().map(|code| KeyboardKey::KeyCode(code)), + )), + try(( + many1(key_modifier()), + action_character().map(|c| + KeyboardKey::Character(Character::new(c)) + ), + )) + ) + ).map(|(modifiers, key): (Vec, KeyboardKey)| { + let modifiers = if modifiers.is_empty() { + None + } else { + Some(modifiers) + }; + + KeyboardKeyWithModifiers::new( + key, + modifiers, ) + }) } -fn key_modifiers() -> impl Parser>> +fn key_modifier() -> impl Parser where I: Stream, I::Error: ParseError, { - many( - choice!( - try(string_case_insensitive("D-")) - .map(|_| Flag::Control), - try(string_case_insensitive("A-")) - .map(|_| Flag::Alt), - try(string_case_insensitive("C-")) - .map(|_| Flag::Meta), - try(string_case_insensitive("S-")) - .map(|_| Flag::Shift) - ) - ).map(|modifiers: Vec| - if modifiers.is_empty() { - None - } else { - Some(modifiers) - } + choice!( + try(string_case_insensitive("D-")) + .map(|_| Flag::Meta), + try(string_case_insensitive("A-")) + .map(|_| Flag::Alt), + try(string_case_insensitive("C-")) + .map(|_| Flag::Control), + try(string_case_insensitive("S-")) + .map(|_| Flag::Shift) ) } @@ -576,7 +585,7 @@ mod tests { #[test] fn action_parses_map_with_modifier() { - let text = "onetwothree"; + let text = "onetwo"; let expected = Action::Map(vec![ KeyboardKeyWithModifiers::new( @@ -612,24 +621,8 @@ mod tests { Some(vec![Flag::Meta]), ), KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new('t')), - None, - ), - KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new('h')), - None, - ), - KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new('r')), - None, - ), - KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new('e')), - None, - ), - KeyboardKeyWithModifiers::new( - KeyboardKey::Character(Character::new('e')), - None, + KeyboardKey::KeyCode(KeyCode::new(autopilot::key::KeyCode::LeftArrow)), + Some(vec![Flag::Alt]), ), ]); let result = action_map().easy_parse(text).map(|t| t.0); -- cgit v1.2.3