From 6b964179608211f4fa300ffe4f1885055654123d Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 2 Jan 2024 16:48:31 -0500 Subject: [PATCH] Normalize `S-` keymaps to uppercase ascii Keymaps that use the shift modifier and a lowercase ascii character should be equivalent to keymaps that use just the uppercase of that ascii character. We can normalize key events as we parse them out of strings so that both representations parse to the same event. This allows mapping keys like `C-S-r` which previously could only be bound by `C-R`. --- helix-view/src/input.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs index 0f4ffaacf9cc..5f5067eac9f8 100644 --- a/helix-view/src/input.rs +++ b/helix-view/src/input.rs @@ -325,7 +325,7 @@ impl std::str::FromStr for KeyEvent { fn from_str(s: &str) -> Result { let mut tokens: Vec<_> = s.split('-').collect(); - let code = match tokens.pop().ok_or_else(|| anyhow!("Missing key code"))? { + let mut code = match tokens.pop().ok_or_else(|| anyhow!("Missing key code"))? { keys::BACKSPACE => KeyCode::Backspace, keys::ENTER => KeyCode::Enter, keys::LEFT => KeyCode::Left, @@ -405,6 +405,18 @@ impl std::str::FromStr for KeyEvent { modifiers.insert(flag); } + // Normalize character keys so that characters like C-S-r and C-R + // are represented by equal KeyEvents. + match code { + KeyCode::Char(ch) + if ch.is_ascii_lowercase() && modifiers.contains(KeyModifiers::SHIFT) => + { + code = KeyCode::Char(ch.to_ascii_uppercase()); + modifiers.remove(KeyModifiers::SHIFT); + } + _ => (), + } + Ok(KeyEvent { code, modifiers }) } } @@ -684,6 +696,19 @@ mod test { modifiers: KeyModifiers::ALT | KeyModifiers::CONTROL } ); + + assert_eq!( + str::parse::("C-S-r").unwrap(), + str::parse::("C-R").unwrap(), + ); + + assert_eq!( + str::parse::("S-w").unwrap(), + KeyEvent { + code: KeyCode::Char('W'), + modifiers: KeyModifiers::NONE + } + ); } #[test]