diff options
| author | Teddy Wing | 2018-09-30 20:43:27 +0200 | 
|---|---|---|
| committer | Teddy Wing | 2018-09-30 20:43:27 +0200 | 
| commit | dc606d756ceecf5ae8a52e607fd4a68727fd2529 (patch) | |
| tree | 12321df9e5df7462ae875193ea61ac8872a21a03 /src/parser.rs | |
| parent | 7801f2561227526e7bacf9915bb4d7f63cf14449 (diff) | |
| download | dome-key-map-dc606d756ceecf5ae8a52e607fd4a68727fd2529.tar.bz2 | |
special_key(): Handle modifier + character special keys
Previously we were able to parse modifier + KeyCode (`<C-Enter>`) special
keys and plain KeyCode ones (`<Esc>`).
This change adds parsing support for the final type of special key,
modifier + character (e.g. `<C-l>`).
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:
    <C-l>      // 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.
Diffstat (limited to 'src/parser.rs')
| -rw-r--r-- | src/parser.rs | 101 | 
1 files changed, 47 insertions, 54 deletions
| 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<I>() -> impl Parser<Input = I, Output = KeyboardKeyWithModifiers> +fn action_character<I>() -> impl Parser<Input = I, Output = char>  where      I: Stream<Item = char>,      I::Error: ParseError<I::Item, I::Range, I::Position>, @@ -223,12 +229,6 @@ where          satisfy(|c| c != '<' && c != '\\'),          action_escape()      ) -        .map(|c| -            KeyboardKeyWithModifiers::new( -                KeyboardKey::Character(Character::new(c)), -                None, -            ) -        )  }  fn action_escape<I>() -> impl Parser<Input = I, Output = char> @@ -247,40 +247,49 @@ where      I: Stream<Item = char>,      I::Error: ParseError<I::Item, I::Range, I::Position>,  { -    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<Flag>, KeyboardKey)| { +        let modifiers = if modifiers.is_empty() { +            None +        } else { +            Some(modifiers) +        }; + +        KeyboardKeyWithModifiers::new( +            key, +            modifiers,          ) +    })  } -fn key_modifiers<I>() -> impl Parser<Input = I, Output = Option<Vec<Flag>>> +fn key_modifier<I>() -> impl Parser<Input = I, Output = Flag>  where      I: Stream<Item = char>,      I::Error: ParseError<I::Item, I::Range, I::Position>,  { -    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<Flag>| -        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 = "one<C-l>two<D-s>three"; +        let text = "one<C-l>two<D-s><A-Left>";          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); | 
