feat(tui): declarative keymap + command registry
This commit is contained in:
105
crates/owlen-tui/src/commands/registry.rs
Normal file
105
crates/owlen-tui/src/commands/registry.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use owlen_core::ui::FocusedPanel;
|
||||
|
||||
use crate::widgets::model_picker::FilterMode;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum AppCommand {
|
||||
OpenModelPicker(FilterMode),
|
||||
OpenCommandPalette,
|
||||
CycleFocusForward,
|
||||
CycleFocusBackward,
|
||||
FocusPanel(FocusedPanel),
|
||||
ComposerSubmit,
|
||||
EnterCommandMode,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommandRegistry {
|
||||
commands: HashMap<String, AppCommand>,
|
||||
}
|
||||
|
||||
impl CommandRegistry {
|
||||
pub fn new() -> Self {
|
||||
let mut commands = HashMap::new();
|
||||
|
||||
commands.insert(
|
||||
"model.open_all".to_string(),
|
||||
AppCommand::OpenModelPicker(FilterMode::All),
|
||||
);
|
||||
commands.insert(
|
||||
"model.open_local".to_string(),
|
||||
AppCommand::OpenModelPicker(FilterMode::LocalOnly),
|
||||
);
|
||||
commands.insert(
|
||||
"model.open_cloud".to_string(),
|
||||
AppCommand::OpenModelPicker(FilterMode::CloudOnly),
|
||||
);
|
||||
commands.insert(
|
||||
"model.open_available".to_string(),
|
||||
AppCommand::OpenModelPicker(FilterMode::Available),
|
||||
);
|
||||
commands.insert("palette.open".to_string(), AppCommand::OpenCommandPalette);
|
||||
commands.insert("focus.next".to_string(), AppCommand::CycleFocusForward);
|
||||
commands.insert("focus.prev".to_string(), AppCommand::CycleFocusBackward);
|
||||
commands.insert(
|
||||
"focus.files".to_string(),
|
||||
AppCommand::FocusPanel(FocusedPanel::Files),
|
||||
);
|
||||
commands.insert(
|
||||
"focus.chat".to_string(),
|
||||
AppCommand::FocusPanel(FocusedPanel::Chat),
|
||||
);
|
||||
commands.insert(
|
||||
"focus.thinking".to_string(),
|
||||
AppCommand::FocusPanel(FocusedPanel::Thinking),
|
||||
);
|
||||
commands.insert(
|
||||
"focus.input".to_string(),
|
||||
AppCommand::FocusPanel(FocusedPanel::Input),
|
||||
);
|
||||
commands.insert(
|
||||
"focus.code".to_string(),
|
||||
AppCommand::FocusPanel(FocusedPanel::Code),
|
||||
);
|
||||
commands.insert("composer.submit".to_string(), AppCommand::ComposerSubmit);
|
||||
commands.insert("mode.command".to_string(), AppCommand::EnterCommandMode);
|
||||
|
||||
Self { commands }
|
||||
}
|
||||
|
||||
pub fn resolve(&self, command: &str) -> Option<AppCommand> {
|
||||
self.commands.get(command).copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CommandRegistry {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn resolve_known_command() {
|
||||
let registry = CommandRegistry::new();
|
||||
assert_eq!(
|
||||
registry.resolve("focus.next"),
|
||||
Some(AppCommand::CycleFocusForward)
|
||||
);
|
||||
assert_eq!(
|
||||
registry.resolve("model.open_cloud"),
|
||||
Some(AppCommand::OpenModelPicker(FilterMode::CloudOnly))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_unknown_command() {
|
||||
let registry = CommandRegistry::new();
|
||||
assert_eq!(registry.resolve("does.not.exist"), None);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user