diff --git a/client/src/functions/modes/read_only/add_table_ro.rs b/client/src/functions/modes/read_only/add_table_ro.rs index 98f29bb..cb4f621 100644 --- a/client/src/functions/modes/read_only/add_table_ro.rs +++ b/client/src/functions/modes/read_only/add_table_ro.rs @@ -1,7 +1,7 @@ // src/functions/modes/read_only/add_table_ro.rs use crate::config::binds::key_sequences::KeySequenceTracker; use crate::state::pages::add_table::AddTableState; -use crate::state::pages::canvas_state::CanvasState; // Use trait for common actions +use crate::state::pages::canvas_state::CanvasState; use crate::state::app::state::AppState; use anyhow::Result; @@ -80,41 +80,36 @@ pub async fn execute_action( "move_up" => { key_sequence_tracker.reset(); let num_fields = AddTableState::INPUT_FIELD_COUNT; - if num_fields == 0 { return Ok("No fields.".to_string()); } + if num_fields == 0 { + *command_message = "No fields.".to_string(); + return Ok(command_message.clone()); + } let current_field = state.current_field(); // Gets the index (0, 1, or 2) if current_field > 0 { // This handles moving from field 2 -> 1, or 1 -> 0 let new_field = current_field - 1; state.set_current_field(new_field); - // ... (rest of the logic to set cursor position) ... + let current_input = state.get_current_input(); + let max_cursor_pos = current_input.len(); // Allow cursor at end + let new_pos = (*ideal_cursor_column).min(max_cursor_pos); + state.set_current_cursor_pos(new_pos); + *ideal_cursor_column = new_pos; // Update ideal column as cursor moved + *command_message = "".to_string(); // Clear message for successful internal navigation } else { - // --- THIS IS WHERE THE FIX GOES --- // current_field is 0 (InputTableName), and user pressed Up. - // We need to move focus *outside* the canvas. - - // Set the flag to indicate focus is leaving the canvas - app_state.ui.focus_outside_canvas = true; - - // Decide which element gets focus. Based on your layout and the - // downward navigation (CancelButton wraps to InputTableName), - // moving up from InputTableName should likely go to CancelButton. - state.current_focus = crate::state::pages::add_table::AddTableFocus::CancelButton; - - // Reset the sequence tracker as the action is complete - key_sequence_tracker.reset(); - - // Return a message indicating the focus change - return Ok("Focus moved above canvas".to_string()); - // --- END FIX --- + // Forbid moving up. Do not change focus or cursor. + *command_message = "At top of form.".to_string(); } - // If we moved within the canvas (e.g., 1 -> 0), return empty string - Ok("".to_string()) + Ok(command_message.clone()) } "move_down" => { key_sequence_tracker.reset(); let num_fields = AddTableState::INPUT_FIELD_COUNT; - if num_fields == 0 { return Ok("No fields.".to_string()); } + if num_fields == 0 { + *command_message = "No fields.".to_string(); + return Ok(command_message.clone()); + } let current_field = state.current_field(); let last_field_index = num_fields - 1; @@ -125,16 +120,19 @@ pub async fn execute_action( let max_cursor_pos = current_input.len(); // Allow cursor at end let new_pos = (*ideal_cursor_column).min(max_cursor_pos); state.set_current_cursor_pos(new_pos); + *ideal_cursor_column = new_pos; // Update ideal column + *command_message = "".to_string(); } else { // Move focus outside canvas when moving down from the last field app_state.ui.focus_outside_canvas = true; // Set focus to the first element outside canvas (AddColumnButton) - state.current_focus = crate::state::pages::add_table::AddTableFocus::AddColumnButton; - key_sequence_tracker.reset(); - return Ok("Focus moved below canvas".to_string()); + state.current_focus = + crate::state::pages::add_table::AddTableFocus::AddColumnButton; + *command_message = "Focus moved below canvas".to_string(); } - Ok("".to_string()) + Ok(command_message.clone()) } + // ... (other actions like "move_first_line", "move_left", etc. remain the same) ... "move_first_line" => { key_sequence_tracker.reset(); if AddTableState::INPUT_FIELD_COUNT > 0 { @@ -145,7 +143,8 @@ pub async fn execute_action( state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; // Update ideal column } - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_last_line" => { key_sequence_tracker.reset(); @@ -159,14 +158,16 @@ pub async fn execute_action( state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; // Update ideal column } - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_left" => { let current_pos = state.current_cursor_pos(); let new_pos = current_pos.saturating_sub(1); state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_right" => { let current_input = state.get_current_input(); @@ -177,68 +178,90 @@ pub async fn execute_action( state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; } - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_word_next" => { let current_input = state.get_current_input(); - let new_pos = find_next_word_start(current_input, state.current_cursor_pos()); + let new_pos = find_next_word_start( + current_input, + state.current_cursor_pos(), + ); let final_pos = new_pos.min(current_input.len()); // Allow cursor at end state.set_current_cursor_pos(final_pos); *ideal_cursor_column = final_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_word_end" => { let current_input = state.get_current_input(); let current_pos = state.current_cursor_pos(); let new_pos = find_word_end(current_input, current_pos); // If find_word_end returns current_pos, try starting search from next char - let final_pos = if new_pos == current_pos && current_pos < current_input.len() { - find_word_end(current_input, current_pos + 1) - } else { - new_pos - }; + let final_pos = + if new_pos == current_pos && current_pos < current_input.len() { + find_word_end(current_input, current_pos + 1) + } else { + new_pos + }; let max_valid_index = current_input.len(); // Allow cursor at end let clamped_pos = final_pos.min(max_valid_index); state.set_current_cursor_pos(clamped_pos); *ideal_cursor_column = clamped_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_word_prev" => { let current_input = state.get_current_input(); - let new_pos = find_prev_word_start(current_input, state.current_cursor_pos()); + let new_pos = find_prev_word_start( + current_input, + state.current_cursor_pos(), + ); state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_word_end_prev" => { let current_input = state.get_current_input(); - let new_pos = find_prev_word_end(current_input, state.current_cursor_pos()); + let new_pos = find_prev_word_end( + current_input, + state.current_cursor_pos(), + ); state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_line_start" => { state.set_current_cursor_pos(0); *ideal_cursor_column = 0; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } "move_line_end" => { let current_input = state.get_current_input(); let new_pos = current_input.len(); // Allow cursor at end state.set_current_cursor_pos(new_pos); *ideal_cursor_column = new_pos; - Ok("".to_string()) + *command_message = "".to_string(); + Ok(command_message.clone()) } // Actions handled by main event loop (mode changes) - "enter_edit_mode_before" | "enter_edit_mode_after" | "enter_command_mode" | "exit_highlight_mode" => { - key_sequence_tracker.reset(); - Ok("Mode change handled by main loop".to_string()) + "enter_edit_mode_before" | "enter_edit_mode_after" + | "enter_command_mode" | "exit_highlight_mode" => { + key_sequence_tracker.reset(); + // These actions are primarily mode changes handled by the main event loop. + // The message here might be overridden by the main loop's message for mode change. + *command_message = "Mode change initiated".to_string(); + Ok(command_message.clone()) } _ => { - key_sequence_tracker.reset(); - command_message.clear(); // Clear message for unhandled actions - Ok(format!("Unknown read-only action: {}", action)) - }, + key_sequence_tracker.reset(); + *command_message = + format!("Unknown read-only action: {}", action); + Ok(command_message.clone()) + } } }