From 29ea66e861420049f593cbaabace13c091db345a Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sun, 30 Sep 2018 17:45:01 +0200 Subject: action_map(): Add backslash escaping Escape '<' and '\' by prepending a backslash. Since special characters are enclosed in '<' '>' brackets, in order to type a literal '<', we need a way to escape it. Use backslash, like in Vim. --- src/parser.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/src/parser.rs b/src/parser.rs index d82cdaf..37d69df 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -219,7 +219,10 @@ where I: Stream, I::Error: ParseError, { - satisfy(|c| c != '<') + or( + satisfy(|c| c != '<' && c != '\\'), + action_escape() + ) .map(|c| KeyboardKeyWithModifiers::new( KeyboardKey::Character(Character::new(c)), @@ -228,6 +231,17 @@ where ) } +fn action_escape() -> impl Parser +where + I: Stream, + I::Error: ParseError, +{ + choice!( + try(string("\\\\")).map(|_| '\\'), + try(string("\\<")).map(|_| '<') + ) +} + fn special_key() -> impl Parser where I: Stream, @@ -594,10 +608,108 @@ mod tests { #[test] fn action_parses_map_with_backslash_escape() { + let text = "type\\\\onebslash"; + + let expected = Action::Map(vec![ + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('t')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('y')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('p')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('e')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('\\')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('o')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('n')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('e')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('b')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('s')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('l')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('a')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('s')), + None, + ), + KeyboardKeyWithModifiers::new( + KeyboardKey::Character(Character::new('h')), + None, + ), + ]); + let result = action_map().easy_parse(text).map(|t| t.0); + + assert_eq!(result, Ok(expected)); } #[test] fn action_parses_map_with_less_than_escape() { + let text = "type\\