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)
This commit is contained in:
@ -6,6 +6,7 @@ use crossterm::event::{KeyCode, KeyModifiers};
|
|||||||
|
|
||||||
use crate::ui::app::AppMode;
|
use crate::ui::app::AppMode;
|
||||||
use crate::ui::effect::Effect;
|
use crate::ui::effect::Effect;
|
||||||
|
use crate::view::Axis;
|
||||||
|
|
||||||
use super::cmd::{self, Cmd, CmdContext};
|
use super::cmd::{self, Cmd, CmdContext};
|
||||||
|
|
||||||
@ -14,6 +15,9 @@ use super::cmd::{self, Cmd, CmdContext};
|
|||||||
pub enum KeyPattern {
|
pub enum KeyPattern {
|
||||||
/// Single key with modifiers
|
/// Single key with modifiers
|
||||||
Key(KeyCode, KeyModifiers),
|
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.
|
/// Identifies which mode a binding applies to.
|
||||||
@ -22,14 +26,35 @@ pub enum KeyPattern {
|
|||||||
pub enum ModeKey {
|
pub enum ModeKey {
|
||||||
Normal,
|
Normal,
|
||||||
Help,
|
Help,
|
||||||
// More modes can be added as we migrate handlers
|
FormulaPanel,
|
||||||
|
CategoryPanel,
|
||||||
|
ViewPanel,
|
||||||
|
TileSelect,
|
||||||
|
Editing,
|
||||||
|
FormulaEdit,
|
||||||
|
CategoryAdd,
|
||||||
|
ItemAdd,
|
||||||
|
ExportPrompt,
|
||||||
|
CommandMode,
|
||||||
|
SearchMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModeKey {
|
impl ModeKey {
|
||||||
pub fn from_app_mode(mode: &AppMode) -> Option<Self> {
|
pub fn from_app_mode(mode: &AppMode, search_mode: bool) -> Option<Self> {
|
||||||
match mode {
|
match mode {
|
||||||
|
AppMode::Normal if search_mode => Some(ModeKey::SearchMode),
|
||||||
AppMode::Normal => Some(ModeKey::Normal),
|
AppMode::Normal => Some(ModeKey::Normal),
|
||||||
AppMode::Help => Some(ModeKey::Help),
|
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,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,9 +102,22 @@ impl Keymap {
|
|||||||
pub fn lookup(&self, key: KeyCode, mods: KeyModifiers) -> Option<&dyn Cmd> {
|
pub fn lookup(&self, key: KeyCode, mods: KeyModifiers) -> Option<&dyn Cmd> {
|
||||||
self.bindings
|
self.bindings
|
||||||
.get(&KeyPattern::Key(key, mods))
|
.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())
|
.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.
|
/// Execute a keymap lookup and return effects, or None if no binding.
|
||||||
pub fn dispatch(
|
pub fn dispatch(
|
||||||
&self,
|
&self,
|
||||||
@ -133,8 +171,8 @@ impl KeymapSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the root keymap for a given app mode.
|
/// Look up the root keymap for a given app mode.
|
||||||
pub fn get(&self, mode: &AppMode) -> Option<&Arc<Keymap>> {
|
pub fn get(&self, mode: &AppMode, search_mode: bool) -> Option<&Arc<Keymap>> {
|
||||||
let mode_key = ModeKey::from_app_mode(mode)?;
|
let mode_key = ModeKey::from_app_mode(mode, search_mode)?;
|
||||||
self.mode_maps.get(&mode_key)
|
self.mode_maps.get(&mode_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +183,7 @@ impl KeymapSet {
|
|||||||
key: KeyCode,
|
key: KeyCode,
|
||||||
mods: KeyModifiers,
|
mods: KeyModifiers,
|
||||||
) -> Option<Vec<Box<dyn Effect>>> {
|
) -> Option<Vec<Box<dyn Effect>>> {
|
||||||
let keymap = self.get(ctx.mode)?;
|
let keymap = self.get(ctx.mode, ctx.search_mode)?;
|
||||||
keymap.dispatch(ctx, key, mods)
|
keymap.dispatch(ctx, key, mods)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user