From e976b3c49a9e47d4bab7ee567ea7ea8cd3e63630 Mon Sep 17 00:00:00 2001 From: Edward Langley Date: Sat, 4 Apr 2026 09:58:31 -0700 Subject: [PATCH] feat(keymap): add AnyChar pattern and new mode variants Add AnyChar key pattern for text-entry modes that matches any Char key. Add new mode variants to ModeKey: FormulaPanel, CategoryPanel, ViewPanel, TileSelect, Editing, FormulaEdit, CategoryAdd, ItemAdd, ExportPrompt, CommandMode, and SearchMode. Update Keymap::lookup to fall back to AnyChar for Char keys. Update KeymapSet::get to accept search_mode parameter. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M) --- src/command/keymap.rs | 48 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/command/keymap.rs b/src/command/keymap.rs index f258717..a1aab5b 100644 --- a/src/command/keymap.rs +++ b/src/command/keymap.rs @@ -6,6 +6,7 @@ use crossterm::event::{KeyCode, KeyModifiers}; use crate::ui::app::AppMode; use crate::ui::effect::Effect; +use crate::view::Axis; use super::cmd::{self, Cmd, CmdContext}; @@ -14,6 +15,9 @@ use super::cmd::{self, Cmd, CmdContext}; pub enum KeyPattern { /// Single key with modifiers Key(KeyCode, KeyModifiers), + /// Matches any Char key (for text-entry modes). The actual char + /// is available in CmdContext::key_code. + AnyChar, } /// Identifies which mode a binding applies to. @@ -22,14 +26,35 @@ pub enum KeyPattern { pub enum ModeKey { Normal, Help, - // More modes can be added as we migrate handlers + FormulaPanel, + CategoryPanel, + ViewPanel, + TileSelect, + Editing, + FormulaEdit, + CategoryAdd, + ItemAdd, + ExportPrompt, + CommandMode, + SearchMode, } impl ModeKey { - pub fn from_app_mode(mode: &AppMode) -> Option { + pub fn from_app_mode(mode: &AppMode, search_mode: bool) -> Option { match mode { + AppMode::Normal if search_mode => Some(ModeKey::SearchMode), AppMode::Normal => Some(ModeKey::Normal), AppMode::Help => Some(ModeKey::Help), + AppMode::FormulaPanel => Some(ModeKey::FormulaPanel), + AppMode::CategoryPanel => Some(ModeKey::CategoryPanel), + AppMode::ViewPanel => Some(ModeKey::ViewPanel), + AppMode::TileSelect => Some(ModeKey::TileSelect), + AppMode::Editing { .. } => Some(ModeKey::Editing), + AppMode::FormulaEdit { .. } => Some(ModeKey::FormulaEdit), + AppMode::CategoryAdd { .. } => Some(ModeKey::CategoryAdd), + AppMode::ItemAdd { .. } => Some(ModeKey::ItemAdd), + AppMode::ExportPrompt { .. } => Some(ModeKey::ExportPrompt), + AppMode::CommandMode { .. } => Some(ModeKey::CommandMode), _ => None, } } @@ -77,9 +102,22 @@ impl Keymap { pub fn lookup(&self, key: KeyCode, mods: KeyModifiers) -> Option<&dyn Cmd> { self.bindings .get(&KeyPattern::Key(key, mods)) + .or_else(|| { + // Fall back to AnyChar for text-entry modes + if matches!(key, KeyCode::Char(_)) { + self.bindings.get(&KeyPattern::AnyChar) + } else { + None + } + }) .map(|c| c.as_ref()) } + /// Bind a catch-all for any Char key (used for text-entry modes). + pub fn bind_any_char(&mut self, cmd: impl Cmd + 'static) { + self.bindings.insert(KeyPattern::AnyChar, Arc::new(cmd)); + } + /// Execute a keymap lookup and return effects, or None if no binding. pub fn dispatch( &self, @@ -133,8 +171,8 @@ impl KeymapSet { } /// Look up the root keymap for a given app mode. - pub fn get(&self, mode: &AppMode) -> Option<&Arc> { - let mode_key = ModeKey::from_app_mode(mode)?; + pub fn get(&self, mode: &AppMode, search_mode: bool) -> Option<&Arc> { + let mode_key = ModeKey::from_app_mode(mode, search_mode)?; self.mode_maps.get(&mode_key) } @@ -145,7 +183,7 @@ impl KeymapSet { key: KeyCode, mods: KeyModifiers, ) -> Option>> { - let keymap = self.get(ctx.mode)?; + let keymap = self.get(ctx.mode, ctx.search_mode)?; keymap.dispatch(ctx, key, mods) }