From 0f1de6ba58d365745f354db58daa0709f1b9c153 Mon Sep 17 00:00:00 2001 From: Edward Langley Date: Sat, 4 Apr 2026 18:37:43 -0700 Subject: [PATCH] refactor(keymap): add Char key fallback and remove unused SHIFT binding Improve keymap lookup for Char keys by adding fallback to NONE modifiers. Terminals vary in whether they send SHIFT for uppercase/symbol characters, so we now retry without modifiers when an exact match fails. Also removed the unused shift variable and updated key bindings to use NONE modifiers instead of SHIFT for consistency. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M) --- src/command/keymap.rs | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/command/keymap.rs b/src/command/keymap.rs index 3b6ee53..2c0424c 100644 --- a/src/command/keymap.rs +++ b/src/command/keymap.rs @@ -133,9 +133,21 @@ impl Keymap { } /// Look up the binding for a key. + /// For Char keys, if exact (key, mods) match fails, retries with NONE + /// modifiers since terminals vary in whether they send SHIFT for + /// uppercase/symbol characters. pub fn lookup(&self, key: KeyCode, mods: KeyModifiers) -> Option<&Binding> { self.bindings .get(&KeyPattern::Key(key, mods)) + .or_else(|| { + // Retry Char keys without modifiers (shift is implicit in the char) + if matches!(key, KeyCode::Char(_)) && mods != KeyModifiers::NONE { + self.bindings + .get(&KeyPattern::Key(key, KeyModifiers::NONE)) + } else { + None + } + }) .or_else(|| { if matches!(key, KeyCode::Char(_)) { self.bindings.get(&KeyPattern::AnyChar) @@ -222,7 +234,6 @@ impl KeymapSet { let mut set = Self::new(registry); let none = KeyModifiers::NONE; let ctrl = KeyModifiers::CONTROL; - let shift = KeyModifiers::SHIFT; // ── Normal mode ────────────────────────────────────────────────── let mut normal = Keymap::new(); @@ -251,9 +262,9 @@ impl KeymapSet { } // Jump to boundaries - normal.bind(KeyCode::Char('G'), shift, "jump-last-row"); + normal.bind(KeyCode::Char('G'), none, "jump-last-row"); normal.bind(KeyCode::Char('0'), none, "jump-first-col"); - normal.bind(KeyCode::Char('$'), shift, "jump-last-col"); + normal.bind(KeyCode::Char('$'), none, "jump-last-col"); // Scroll normal.bind_args(KeyCode::Char('d'), ctrl, "scroll-rows", vec!["5".into()]); @@ -270,7 +281,7 @@ impl KeymapSet { normal.bind(KeyCode::Char('q'), ctrl, "force-quit"); normal.bind_args( KeyCode::Char(':'), - shift, + none, "enter-mode", vec!["command".into()], ); @@ -278,24 +289,24 @@ impl KeymapSet { normal.bind(KeyCode::Char('s'), ctrl, "save"); normal.bind(KeyCode::F(1), none, "enter-mode"); normal.bind_args(KeyCode::F(1), none, "enter-mode", vec!["help".into()]); - normal.bind_args(KeyCode::Char('?'), shift, "enter-mode", vec!["help".into()]); + normal.bind_args(KeyCode::Char('?'), none, "enter-mode", vec!["help".into()]); // Panel toggles normal.bind_args( KeyCode::Char('F'), - shift, + none, "toggle-panel-and-focus", vec!["formula".into()], ); normal.bind_args( KeyCode::Char('C'), - shift, + none, "toggle-panel-and-focus", vec!["category".into()], ); normal.bind_args( KeyCode::Char('V'), - shift, + none, "toggle-panel-and-focus", vec!["view".into()], ); @@ -332,7 +343,7 @@ impl KeymapSet { "search-navigate", vec!["forward".into()], ); - normal.bind(KeyCode::Char('N'), shift, "search-or-category-add"); + normal.bind(KeyCode::Char('N'), none, "search-or-category-add"); // Page navigation normal.bind(KeyCode::Char(']'), none, "page-next"); @@ -340,10 +351,10 @@ impl KeymapSet { // Group / hide normal.bind(KeyCode::Char('z'), none, "toggle-group-under-cursor"); - normal.bind(KeyCode::Char('H'), shift, "hide-selected-row-item"); + normal.bind(KeyCode::Char('H'), none, "hide-selected-row-item"); // Tile select - normal.bind(KeyCode::Char('T'), shift, "enter-tile-select"); + normal.bind(KeyCode::Char('T'), none, "enter-tile-select"); normal.bind(KeyCode::Left, ctrl, "enter-tile-select"); normal.bind(KeyCode::Right, ctrl, "enter-tile-select"); normal.bind(KeyCode::Up, ctrl, "enter-tile-select"); @@ -360,8 +371,8 @@ impl KeymapSet { normal.bind_prefix(KeyCode::Char('y'), none, Arc::new(y_map)); let mut z_map = Keymap::new(); - z_map.bind(KeyCode::Char('Z'), shift, "save-and-quit"); - normal.bind_prefix(KeyCode::Char('Z'), shift, Arc::new(z_map)); + z_map.bind(KeyCode::Char('Z'), none, "save-and-quit"); + normal.bind_prefix(KeyCode::Char('Z'), none, Arc::new(z_map)); set.insert(ModeKey::Normal, Arc::new(normal));