|
|
|
|
@@ -2,7 +2,6 @@
|
|
|
|
|
|
|
|
|
|
use crossterm::event::{KeyEvent};
|
|
|
|
|
use crate::config::binds::config::Config;
|
|
|
|
|
use crate::modes::handlers::read_only::ReadOnlyHandler;
|
|
|
|
|
use crate::state::pages::form::FormState;
|
|
|
|
|
use crate::config::binds::key_sequences::KeySequenceTracker;
|
|
|
|
|
use crate::tui::terminal::grpc_client::GrpcClient;
|
|
|
|
|
@@ -17,6 +16,7 @@ enum CharType {
|
|
|
|
|
pub async fn handle_read_only_event(
|
|
|
|
|
key: KeyEvent,
|
|
|
|
|
config: &Config,
|
|
|
|
|
form_state: &mut FormState,
|
|
|
|
|
key_sequence_tracker: &mut KeySequenceTracker,
|
|
|
|
|
current_position: &mut u64,
|
|
|
|
|
total_count: u64,
|
|
|
|
|
@@ -24,9 +24,8 @@ pub async fn handle_read_only_event(
|
|
|
|
|
command_message: &mut String,
|
|
|
|
|
edit_mode_cooldown: &mut bool,
|
|
|
|
|
ideal_cursor_column: &mut usize,
|
|
|
|
|
handler: &mut dyn ReadOnlyHandler,
|
|
|
|
|
) -> Result<(bool, String), Box<dyn std::error::Error>> {
|
|
|
|
|
// Check edit mode transitions first
|
|
|
|
|
// Check for entering Edit mode from Read-Only mode
|
|
|
|
|
if config.is_enter_edit_mode_before(key.code, key.modifiers) {
|
|
|
|
|
*edit_mode_cooldown = true;
|
|
|
|
|
*command_message = "Entering Edit mode".to_string();
|
|
|
|
|
@@ -34,26 +33,88 @@ pub async fn handle_read_only_event(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if config.is_enter_edit_mode_after(key.code, key.modifiers) {
|
|
|
|
|
handler.adjust_cursor_position(ideal_cursor_column);
|
|
|
|
|
let current_input = form_state.get_current_input();
|
|
|
|
|
if !current_input.is_empty() && form_state.current_cursor_pos < current_input.len() {
|
|
|
|
|
form_state.current_cursor_pos += 1;
|
|
|
|
|
*ideal_cursor_column = form_state.current_cursor_pos;
|
|
|
|
|
}
|
|
|
|
|
*edit_mode_cooldown = true;
|
|
|
|
|
*command_message = "Entering Edit mode (after cursor)".to_string();
|
|
|
|
|
return Ok((false, command_message.clone()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process key bindings
|
|
|
|
|
// Handle Read-Only mode keybindings
|
|
|
|
|
if key.modifiers.is_empty() {
|
|
|
|
|
key_sequence_tracker.add_key(key.code);
|
|
|
|
|
let sequence = key_sequence_tracker.get_sequence();
|
|
|
|
|
let action = config.get_read_only_action_for_key(key.code, key.modifiers)
|
|
|
|
|
.or_else(|| config.matches_key_sequence_generalized(&sequence))
|
|
|
|
|
.unwrap_or("unknown");
|
|
|
|
|
|
|
|
|
|
let result = handler.handle_read_only_action(
|
|
|
|
|
&action,
|
|
|
|
|
grpc_client,
|
|
|
|
|
// Try to match the current sequence against Read-Only mode bindings
|
|
|
|
|
if let Some(action) = config.matches_key_sequence_generalized(&sequence) {
|
|
|
|
|
let result = execute_action(
|
|
|
|
|
action,
|
|
|
|
|
form_state,
|
|
|
|
|
ideal_cursor_column,
|
|
|
|
|
key_sequence_tracker,
|
|
|
|
|
command_message,
|
|
|
|
|
current_position,
|
|
|
|
|
total_count
|
|
|
|
|
total_count,
|
|
|
|
|
grpc_client,
|
|
|
|
|
).await?;
|
|
|
|
|
key_sequence_tracker.reset();
|
|
|
|
|
return Ok((false, result));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok((false, result))
|
|
|
|
|
// Check if this might be a prefix of a longer sequence
|
|
|
|
|
if config.is_key_sequence_prefix(&sequence) {
|
|
|
|
|
return Ok((false, command_message.clone()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since it's not part of a multi-key sequence, check for a direct action
|
|
|
|
|
if sequence.len() == 1 && !config.is_key_sequence_prefix(&sequence) {
|
|
|
|
|
if let Some(action) = config.get_read_only_action_for_key(key.code, key.modifiers) {
|
|
|
|
|
let result = execute_action(
|
|
|
|
|
action,
|
|
|
|
|
form_state,
|
|
|
|
|
ideal_cursor_column,
|
|
|
|
|
key_sequence_tracker,
|
|
|
|
|
command_message,
|
|
|
|
|
current_position,
|
|
|
|
|
total_count,
|
|
|
|
|
grpc_client,
|
|
|
|
|
).await?;
|
|
|
|
|
key_sequence_tracker.reset();
|
|
|
|
|
return Ok((false, result));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// If modifiers are pressed, check for direct key bindings
|
|
|
|
|
key_sequence_tracker.reset();
|
|
|
|
|
|
|
|
|
|
if let Some(action) = config.get_read_only_action_for_key(key.code, key.modifiers) {
|
|
|
|
|
let result = execute_action(
|
|
|
|
|
action,
|
|
|
|
|
form_state,
|
|
|
|
|
ideal_cursor_column,
|
|
|
|
|
key_sequence_tracker,
|
|
|
|
|
command_message,
|
|
|
|
|
current_position,
|
|
|
|
|
total_count,
|
|
|
|
|
grpc_client,
|
|
|
|
|
).await?;
|
|
|
|
|
return Ok((false, result));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show a helpful message when no binding was found
|
|
|
|
|
if !*edit_mode_cooldown {
|
|
|
|
|
let default_key = "i".to_string();
|
|
|
|
|
let edit_key = config.keybindings.read_only.get("enter_edit_mode_before")
|
|
|
|
|
.and_then(|keys| keys.first())
|
|
|
|
|
.unwrap_or(&default_key);
|
|
|
|
|
*command_message = format!("Read-only mode - press {} to edit", edit_key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok((false, command_message.clone()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn execute_action(
|
|
|
|
|
|