diff --git a/config.toml b/config.toml index 6acf2b1..18f6827 100644 --- a/config.toml +++ b/config.toml @@ -9,7 +9,7 @@ exit_edit_mode = ["esc", "ctrl+e"] previous_position = ["Left", "9"] next_position = ["Right", "8"] -# move_left = ["h", "Left"] -# move_right = ["l", "Right"] +move_left = ["h"] +move_right = ["l"] # move_up = ["k", "Up"] # move_down = ["j", "Down"] diff --git a/src/client/components1/handlers/form.rs b/src/client/components1/handlers/form.rs index b271ae6..d851a89 100644 --- a/src/client/components1/handlers/form.rs +++ b/src/client/components1/handlers/form.rs @@ -128,8 +128,8 @@ pub fn render_form( } if is_active { if is_edit_mode { - // Edit mode: cursor at the end - let cursor_x = input_rows[i].x + input.len() as u16; + // Edit mode: cursor at current_cursor_pos instead of end + let cursor_x = input_rows[i].x + form_state.current_cursor_pos as u16; let cursor_y = input_rows[i].y; f.set_cursor(cursor_x, cursor_y); } else { diff --git a/src/client/ui/handlers/event.rs b/src/client/ui/handlers/event.rs index e2196a0..1941501 100644 --- a/src/client/ui/handlers/event.rs +++ b/src/client/ui/handlers/event.rs @@ -41,6 +41,9 @@ impl EventHandler { self.edit_mode_cooldown = true; self.command_message = "Edit mode".to_string(); app_terminal.set_cursor_style(SetCursorStyle::BlinkingBar)?; // Add this line + // Initialize cursor position when entering edit mode + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); return Ok((false, self.command_message.clone())); } else if self.is_edit_mode && config.is_exit_edit_mode(key.code, key.modifiers) { // Prevent exiting edit mode if there are unsaved changes @@ -193,7 +196,7 @@ impl EventHandler { } } } else { - // Existing edit mode handling + // Edit mode handling if self.command_mode { match key.code { KeyCode::Enter => { @@ -304,124 +307,148 @@ impl EventHandler { _ => {} } } else { - // Check for keybindings - if let Some(action) = config.get_action_for_key(key.code, key.modifiers) { - let form_data = PostAdresarRequest { - firma: form_state.firma.clone(), - kz: form_state.kz.clone(), - drc: form_state.drc.clone(), - ulica: form_state.ulica.clone(), - psc: form_state.psc.clone(), - mesto: form_state.mesto.clone(), - stat: form_state.stat.clone(), - banka: form_state.banka.clone(), - ucet: form_state.ucet.clone(), - skladm: form_state.skladm.clone(), - ico: form_state.ico.clone(), - kontakt: form_state.kontakt.clone(), - telefon: form_state.telefon.clone(), - skladu: form_state.skladu.clone(), - fax: form_state.fax.clone(), - }; - - let (should_exit, message) = app_terminal - .handle_command(action, is_saved, &form_data) - .await?; - self.command_message = message; - return Ok((should_exit, self.command_message.clone())); - } else { - match key.code { - KeyCode::Char(':') => { - self.command_mode = true; - self.command_input.clear(); - self.command_message.clear(); + // Handle arrow keys in edit mode + match key.code { + KeyCode::Left => { + // Move cursor left + form_state.current_cursor_pos = form_state.current_cursor_pos.saturating_sub(1); + return Ok((false, "".to_string())); + } + KeyCode::Right => { + // Move cursor right + let current_input = form_state.get_current_input(); + if form_state.current_cursor_pos < current_input.len() { + form_state.current_cursor_pos += 1; } - KeyCode::Tab => { - if key.modifiers.contains(KeyModifiers::SHIFT) { - if form_state.current_field == 0 { - // Wrap to the last field when at the top - form_state.current_field = form_state.fields.len() - 1; - } else { - form_state.current_field = form_state.current_field.saturating_sub(1); - } + return Ok((false, "".to_string())); + } + KeyCode::Char(':') => { + self.command_mode = true; + self.command_input.clear(); + self.command_message.clear(); + } + KeyCode::Tab => { + if key.modifiers.contains(KeyModifiers::SHIFT) { + if form_state.current_field == 0 { + // Wrap to the last field when at the top + form_state.current_field = form_state.fields.len() - 1; } else { - form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(); + form_state.current_field = form_state.current_field.saturating_sub(1); } + } else { + form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(); } - KeyCode::Esc => { - if config.is_exit_edit_mode(key.code, key.modifiers) { - if form_state.has_unsaved_changes { - self.command_message = "Unsaved changes! Use :w to save or :q! to discard".to_string(); - return Ok((false, self.command_message.clone())); - } - self.is_edit_mode = false; - self.edit_mode_cooldown = true; - self.command_message = "Read-only mode".to_string(); + // Reset cursor position to end of field when changing fields + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); + } + KeyCode::Esc => { + if config.is_exit_edit_mode(key.code, key.modifiers) { + if form_state.has_unsaved_changes { + self.command_message = "Unsaved changes! Use :w to save or :q! to discard".to_string(); return Ok((false, self.command_message.clone())); } + self.is_edit_mode = false; + self.edit_mode_cooldown = true; + self.command_message = "Read-only mode".to_string(); + return Ok((false, self.command_message.clone())); } - KeyCode::BackTab => { - if form_state.current_field == 0 { - // Wrap to the last field when at the top - form_state.current_field = form_state.fields.len() - 1; - } else { - form_state.current_field = form_state.current_field.saturating_sub(1); - } - }, - KeyCode::Down => form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(), - KeyCode::Up => { - if form_state.current_field == 0 { - // Wrap to the last field when at the top - form_state.current_field = form_state.fields.len() - 1; - } else { - form_state.current_field = form_state.current_field.saturating_sub(1); - } - }, - KeyCode::Enter => form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(), - KeyCode::Char(c) => { - match form_state.current_field { - 0 => form_state.firma.push(c), - 1 => form_state.kz.push(c), - 2 => form_state.drc.push(c), - 3 => form_state.ulica.push(c), - 4 => form_state.psc.push(c), - 5 => form_state.mesto.push(c), - 6 => form_state.stat.push(c), - 7 => form_state.banka.push(c), - 8 => form_state.ucet.push(c), - 9 => form_state.skladm.push(c), - 10 => form_state.ico.push(c), - 11 => form_state.kontakt.push(c), - 12 => form_state.telefon.push(c), - 13 => form_state.skladu.push(c), - 14 => form_state.fax.push(c), - _ => (), - } - form_state.has_unsaved_changes = true; // Mark as unsaved - } - KeyCode::Backspace => { - match form_state.current_field { - 0 => form_state.firma.pop(), - 1 => form_state.kz.pop(), - 2 => form_state.drc.pop(), - 3 => form_state.ulica.pop(), - 4 => form_state.psc.pop(), - 5 => form_state.mesto.pop(), - 6 => form_state.stat.pop(), - 7 => form_state.banka.pop(), - 8 => form_state.ucet.pop(), - 9 => form_state.skladm.pop(), - 10 => form_state.ico.pop(), - 11 => form_state.kontakt.pop(), - 12 => form_state.telefon.pop(), - 13 => form_state.skladu.pop(), - 14 => form_state.fax.pop(), - _ => None, - }; - form_state.has_unsaved_changes = true; // Mark as unsaved - } - _ => {} } + KeyCode::BackTab => { + if form_state.current_field == 0 { + // Wrap to the last field when at the top + form_state.current_field = form_state.fields.len() - 1; + } else { + form_state.current_field = form_state.current_field.saturating_sub(1); + } + // Reset cursor position to end of field when changing fields + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); + }, + KeyCode::Down => { + form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(); + // Reset cursor position to end of field when changing fields + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); + }, + KeyCode::Up => { + if form_state.current_field == 0 { + // Wrap to the last field when at the top + form_state.current_field = form_state.fields.len() - 1; + } else { + form_state.current_field = form_state.current_field.saturating_sub(1); + } + // Reset cursor position to end of field when changing fields + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); + }, + KeyCode::Enter => { + form_state.current_field = (form_state.current_field + 1) % form_state.fields.len(); + // Reset cursor position to end of field when changing fields + let current_input = form_state.get_current_input(); + form_state.current_cursor_pos = current_input.len(); + }, + KeyCode::Char(c) => { + // Save cursor position before mutable borrow + let cursor_pos = form_state.current_cursor_pos; + + // Get the current field value + let field_value = form_state.get_current_input_mut(); + + // Insert character at cursor position instead of just appending + let mut chars: Vec = field_value.chars().collect(); + if cursor_pos <= chars.len() { + chars.insert(cursor_pos, c); + *field_value = chars.into_iter().collect(); + + // Move cursor forward after updating the field + form_state.current_cursor_pos = cursor_pos + 1; + form_state.has_unsaved_changes = true; // Mark as unsaved + } + } + + // Fix for the Backspace handler + KeyCode::Backspace => { + // Only delete if cursor is not at the beginning + if form_state.current_cursor_pos > 0 { + // Save cursor position before mutable borrow + let cursor_pos = form_state.current_cursor_pos; + + // Get the current field value + let field_value = form_state.get_current_input_mut(); + + // Remove character at cursor position - 1 + let mut chars: Vec = field_value.chars().collect(); + if cursor_pos <= chars.len() && cursor_pos > 0 { + chars.remove(cursor_pos - 1); + *field_value = chars.into_iter().collect(); + + // Update cursor position after modifying the field + form_state.current_cursor_pos = cursor_pos - 1; + form_state.has_unsaved_changes = true; // Mark as unsaved + } + } + } + + // Fix for the Delete handler + KeyCode::Delete => { + // Save cursor position before mutable borrow + let cursor_pos = form_state.current_cursor_pos; + + // Get the current field value + let field_value = form_state.get_current_input_mut(); + + // Check if there's a character at cursor position to delete + let chars: Vec = field_value.chars().collect(); + if cursor_pos < chars.len() { + let mut new_chars = chars.clone(); + new_chars.remove(cursor_pos); + *field_value = new_chars.into_iter().collect(); + form_state.has_unsaved_changes = true; // Mark as unsaved + // Cursor position doesn't change with delete + } + } + _ => {} } } } diff --git a/src/client/ui/handlers/form.rs b/src/client/ui/handlers/form.rs index 284c2c3..e36ba60 100644 --- a/src/client/ui/handlers/form.rs +++ b/src/client/ui/handlers/form.rs @@ -117,4 +117,25 @@ impl FormState { _ => "", } } + + pub fn get_current_input_mut(&mut self) -> &mut String { + match self.current_field { + 0 => &mut self.firma, + 1 => &mut self.kz, + 2 => &mut self.drc, + 3 => &mut self.ulica, + 4 => &mut self.psc, + 5 => &mut self.mesto, + 6 => &mut self.stat, + 7 => &mut self.banka, + 8 => &mut self.ucet, + 9 => &mut self.skladm, + 10 => &mut self.ico, + 11 => &mut self.kontakt, + 12 => &mut self.telefon, + 13 => &mut self.skladu, + 14 => &mut self.fax, + _ => &mut self.firma, // Default to first field + } + } }