diff --git a/client/config.toml b/client/config.toml index 1388df4..d23936e 100644 --- a/client/config.toml +++ b/client/config.toml @@ -7,7 +7,6 @@ force_quit = [":q!", "ctrl+shift+q"] save_and_quit = [":wq", "ctrl+shift+s"] enter_command_mode = [":", "ctrl+;"] -exit_command_mode = ["ctrl+g", "esc"] # MODE SPECIFIC # READ ONLY MODE @@ -36,6 +35,11 @@ delete_char_backward = ["backspace"] next_field = ["tab", "enter"] prev_field = ["shift+tab", "backtab"] +# COMMAND MODE +command_execute = ["enter"] +command_backspace = ["backspace"] +exit_command_mode = ["ctrl+g", "esc"] + [colors] theme = "dark" # Options: "light", "dark", "high_contrast" diff --git a/client/src/modes/handlers/command_mode.rs b/client/src/modes/handlers/command_mode.rs index eabde1e..b3bd1ea 100644 --- a/client/src/modes/handlers/command_mode.rs +++ b/client/src/modes/handlers/command_mode.rs @@ -1,9 +1,10 @@ // src/modes/handlers/command_mode.rs -use crossterm::event::{KeyEvent, KeyCode}; +use crossterm::event::{KeyEvent, KeyCode, KeyModifiers}; use crate::tui::terminal::AppTerminal; use crate::config::config::Config; use crate::ui::handlers::form::FormState; +use crate::config::key_sequences::KeySequenceTracker; use common::proto::multieko2::adresar::{PostAdresarRequest, PutAdresarRequest}; pub async fn handle_command_event( @@ -18,81 +19,34 @@ pub async fn handle_command_event( total_count: u64, ) -> Result<(bool, String, bool), Box> { // Return value: (should_exit, message, should_exit_command_mode) - + + // ONLY check for command mode specific actions + // This is a limited set of actions, not all keybindings match key.code { - KeyCode::Enter => { - let command = command_input.trim(); - if command.is_empty() { - *command_message = "Empty command".to_string(); - return Ok((false, command_message.clone(), false)); - } - - let action = config.get_action_for_command(command) - .unwrap_or("unknown"); - - if action == "save" { - let is_new = *current_position == total_count + 1; - - let message = if is_new { - let post_request = PostAdresarRequest { - firma: form_state.values[0].clone(), - kz: form_state.values[1].clone(), - drc: form_state.values[2].clone(), - ulica: form_state.values[3].clone(), - psc: form_state.values[4].clone(), - mesto: form_state.values[5].clone(), - stat: form_state.values[6].clone(), - banka: form_state.values[7].clone(), - ucet: form_state.values[8].clone(), - skladm: form_state.values[9].clone(), - ico: form_state.values[10].clone(), - kontakt: form_state.values[11].clone(), - telefon: form_state.values[12].clone(), - skladu: form_state.values[13].clone(), - fax: form_state.values[14].clone(), - }; - let response = app_terminal.post_adresar(post_request).await?; - let new_total = app_terminal.get_adresar_count().await?; - *current_position = new_total; - form_state.id = response.into_inner().id; - "New entry created".to_string() - } else { - let put_request = PutAdresarRequest { - id: form_state.id, - firma: form_state.values[0].clone(), - kz: form_state.values[1].clone(), - drc: form_state.values[2].clone(), - ulica: form_state.values[3].clone(), - psc: form_state.values[4].clone(), - mesto: form_state.values[5].clone(), - stat: form_state.values[6].clone(), - banka: form_state.values[7].clone(), - ucet: form_state.values[8].clone(), - skladm: form_state.values[9].clone(), - ico: form_state.values[10].clone(), - kontakt: form_state.values[11].clone(), - telefon: form_state.values[12].clone(), - skladu: form_state.values[13].clone(), - fax: form_state.values[14].clone(), - }; - let _ = app_terminal.put_adresar(put_request).await?; - "Entry updated".to_string() - }; - - *is_saved = true; - form_state.has_unsaved_changes = false; + // Check for exit_command_mode action + KeyCode::Esc | KeyCode::Char('g') if key.modifiers.contains(KeyModifiers::CONTROL) => { + if config.is_exit_command_mode(key.code, key.modifiers) { command_input.clear(); - return Ok((false, message, true)); - } else { - let (should_exit, message) = app_terminal - .handle_command(action, is_saved) - .await?; - *command_message = message; - command_input.clear(); - return Ok((should_exit, command_message.clone(), true)); + *command_message = "".to_string(); + return Ok((false, "".to_string(), true)); } } + KeyCode::Enter => { + // Execute the command + return process_command( + config, + form_state, + command_input, + command_message, + app_terminal, + is_saved, + current_position, + total_count, + ).await; + } KeyCode::Char(c) => { + // In command mode, all character keys should be treated as text input + // NOT as potential keybindings command_input.push(c); return Ok((false, "".to_string(), false)); } @@ -100,14 +54,94 @@ pub async fn handle_command_event( command_input.pop(); return Ok((false, "".to_string(), false)); } - KeyCode::Esc => { - command_input.clear(); - *command_message = "".to_string(); - return Ok((false, "".to_string(), true)); - } _ => { - // Ignore other keys + // Ignore other keys - don't process them as keybindings return Ok((false, "".to_string(), false)); } } + + // Default case - nothing matched + Ok((false, "".to_string(), false)) +} + +async fn process_command( + config: &Config, + form_state: &mut FormState, + command_input: &mut String, + command_message: &mut String, + app_terminal: &mut AppTerminal, + is_saved: &mut bool, + current_position: &mut u64, + total_count: u64, +) -> Result<(bool, String, bool), Box> { + let command = command_input.trim(); + if command.is_empty() { + *command_message = "Empty command".to_string(); + return Ok((false, command_message.clone(), false)); + } + + let action = config.get_action_for_command(command) + .unwrap_or("unknown"); + + if action == "save" { + let is_new = *current_position == total_count + 1; + + let message = if is_new { + let post_request = PostAdresarRequest { + firma: form_state.values[0].clone(), + kz: form_state.values[1].clone(), + drc: form_state.values[2].clone(), + ulica: form_state.values[3].clone(), + psc: form_state.values[4].clone(), + mesto: form_state.values[5].clone(), + stat: form_state.values[6].clone(), + banka: form_state.values[7].clone(), + ucet: form_state.values[8].clone(), + skladm: form_state.values[9].clone(), + ico: form_state.values[10].clone(), + kontakt: form_state.values[11].clone(), + telefon: form_state.values[12].clone(), + skladu: form_state.values[13].clone(), + fax: form_state.values[14].clone(), + }; + let response = app_terminal.post_adresar(post_request).await?; + let new_total = app_terminal.get_adresar_count().await?; + *current_position = new_total; + form_state.id = response.into_inner().id; + "New entry created".to_string() + } else { + let put_request = PutAdresarRequest { + id: form_state.id, + firma: form_state.values[0].clone(), + kz: form_state.values[1].clone(), + drc: form_state.values[2].clone(), + ulica: form_state.values[3].clone(), + psc: form_state.values[4].clone(), + mesto: form_state.values[5].clone(), + stat: form_state.values[6].clone(), + banka: form_state.values[7].clone(), + ucet: form_state.values[8].clone(), + skladm: form_state.values[9].clone(), + ico: form_state.values[10].clone(), + kontakt: form_state.values[11].clone(), + telefon: form_state.values[12].clone(), + skladu: form_state.values[13].clone(), + fax: form_state.values[14].clone(), + }; + let _ = app_terminal.put_adresar(put_request).await?; + "Entry updated".to_string() + }; + + *is_saved = true; + form_state.has_unsaved_changes = false; + command_input.clear(); + return Ok((false, message, true)); + } else { + let (should_exit, message) = app_terminal + .handle_command(action, is_saved) + .await?; + *command_message = message; + command_input.clear(); + return Ok((should_exit, command_message.clone(), true)); + } }