diff --git a/client/config.toml b/client/config.toml index 5109841..e8fe1f6 100644 --- a/client/config.toml +++ b/client/config.toml @@ -1,6 +1,13 @@ # config.toml [keybindings] +# [keybindings.global] + +[keybindings.intro] +next_option = ["j", "Right"] +previous_option = ["k", "Left"] +select = ["Enter"] + [keybindings.common] save = ["ctrl+s"] quit = ["ctrl+q"] diff --git a/client/src/config/binds/config.rs b/client/src/config/binds/config.rs index c3c2f41..0029ca3 100644 --- a/client/src/config/binds/config.rs +++ b/client/src/config/binds/config.rs @@ -1,4 +1,4 @@ -// client/src/config/config.rs +// src/config/binds/config.rs use serde::Deserialize; use std::collections::HashMap; @@ -25,6 +25,8 @@ pub struct Config { #[derive(Debug, Deserialize)] pub struct ModeKeybindings { + #[serde(default)] + pub intro: HashMap>, #[serde(default)] pub read_only: HashMap>, #[serde(default)] @@ -33,7 +35,6 @@ pub struct ModeKeybindings { pub command: HashMap>, #[serde(default)] pub common: HashMap>, - // Store top-level keybindings that aren't in a specific mode section #[serde(flatten)] pub global: HashMap>, } @@ -49,6 +50,18 @@ impl Config { Ok(config) } + /// Gets an action for a key in Intro mode, only checking intro and global bindings + pub fn get_intro_action(&self, key: KeyCode, modifiers: KeyModifiers) -> Option<&str> { + self.get_action_for_key_in_mode(&self.keybindings.intro, key, modifiers) + .or_else(|| self.get_action_for_key_in_mode(&self.keybindings.global, key, modifiers)) + } + + /// Gets an action for a key in Admin mode, checking common and global bindings + pub fn get_admin_action(&self, key: KeyCode, modifiers: KeyModifiers) -> Option<&str> { + self.get_action_for_key_in_mode(&self.keybindings.common, key, modifiers) + .or_else(|| self.get_action_for_key_in_mode(&self.keybindings.global, key, modifiers)) + } + /// Gets an action for a key in Read-Only mode, also checking common keybindings. pub fn get_read_only_action_for_key(&self, key: KeyCode, modifiers: KeyModifiers) -> Option<&str> { self.get_action_for_key_in_mode(&self.keybindings.read_only, key, modifiers) @@ -70,6 +83,25 @@ impl Config { .or_else(|| self.get_action_for_key_in_mode(&self.keybindings.global, key, modifiers)) } + /// Context-aware keybinding resolution + pub fn get_action_for_current_context( + &self, + is_edit_mode: bool, + command_mode: bool, + show_intro: bool, + show_admin: bool, + key: KeyCode, + modifiers: KeyModifiers + ) -> Option<&str> { + match (show_intro, show_admin, command_mode, is_edit_mode) { + (true, _, _, _) => self.get_intro_action(key, modifiers), + (_, true, _, _) => self.get_admin_action(key, modifiers), + (_, _, true, _) => self.get_command_action_for_key(key, modifiers), + (_, _, _, true) => self.get_edit_action_for_key(key, modifiers), + _ => self.get_read_only_action_for_key(key, modifiers), + } + } + /// Helper function to get an action for a key in a specific mode. pub fn get_action_for_key_in_mode<'a>( &self, diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index 497a304..6fc020f 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -51,19 +51,16 @@ impl EventHandler { ) -> Result<(bool, String), Box> { if app_state.ui.show_intro { if let Event::Key(key) = event { - match key.code { - KeyCode::Left => intro_state.previous_option(), - KeyCode::Right => intro_state.next_option(), - KeyCode::Enter => { - if intro_state.selected_option == 0 { - app_state.ui.show_intro = false; - } else { - app_state.ui.show_intro = false; - app_state.ui.show_admin = true; - } - return Ok((false, String::new())); - } - _ => {} + let action = config.get_intro_action(key.code, key.modifiers); + + match action { + Some("previous_option") => intro_state.previous_option(), + Some("next_option") => intro_state.next_option(), + Some("select") => { + app_state.ui.show_intro = false; + app_state.ui.show_admin = intro_state.selected_option == 1; + }, + _ => {} // Ignore all other keys } } return Ok((false, String::new()));