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));