fixed example, now working everything properly well

This commit is contained in:
Priec
2025-08-07 23:30:31 +02:00
parent d3e5418221
commit 8e3c85991c
3 changed files with 85 additions and 56 deletions

View File

@@ -217,6 +217,16 @@ impl<D: DataProvider> AutoCursorFormEditor<D> {
Ok(result?)
}
// === SUGGESTIONS CONTROL WRAPPERS ===
fn open_suggestions(&mut self, field_index: usize) {
self.editor.open_suggestions(field_index);
}
fn close_suggestions(&mut self) {
self.editor.close_suggestions();
}
// === MODE TRANSITIONS WITH AUTOMATIC CURSOR MANAGEMENT ===
fn enter_edit_mode(&mut self) {
@@ -541,33 +551,21 @@ async fn handle_key_press(
match (mode, key, modifiers) {
// === SUGGESTIONS HANDLING ===
// Tab: Trigger or navigate suggestions
(_, KeyCode::Tab, _) => {
if editor.is_suggestions_active() {
// Cycle through suggestions
editor.suggestions_next();
editor.set_debug_message("📍 Next suggestion".to_string());
} else if editor.data_provider().supports_suggestions(editor.current_field()) {
let field_names = ["Fruit", "Job", "Language", "Country", "Color"];
let field_name = field_names.get(editor.current_field()).unwrap_or(&"Unknown");
// Open suggestions explicitly
editor.open_suggestions(editor.current_field());
match editor.trigger_suggestions(suggestions_provider).await {
Ok(_) => {
let current_text = editor.current_text();
if editor.suggestions().is_empty() {
if current_text.is_empty() {
editor.set_debug_message(format!("🔍 No {} suggestions available", field_name.to_lowercase()));
} else {
editor.set_debug_message(format!("🔍 No {} matches for '{}'", field_name.to_lowercase(), current_text));
}
} else {
if current_text.is_empty() {
editor.set_debug_message(format!("{} {} suggestions!", editor.suggestions().len(), field_name.to_lowercase()));
} else {
editor.set_debug_message(format!("{} {} matches for '{}'!", editor.suggestions().len(), field_name.to_lowercase(), current_text));
}
}
editor.update_inline_completion();
editor.set_debug_message(format!(
"{} suggestions loaded",
editor.suggestions().len()
));
}
Err(e) => {
editor.set_debug_message(format!("❌ Suggestion error: {}", e));
@@ -595,6 +593,26 @@ async fn handle_key_press(
}
}
// Escape: Close suggestions or exit mode
(_, KeyCode::Esc, _) => {
if editor.is_suggestions_active() {
editor.close_suggestions();
editor.set_debug_message("❌ Suggestions closed".to_string());
} else {
match mode {
AppMode::Edit => {
editor.exit_edit_mode();
}
AppMode::Highlight => {
editor.exit_visual_mode();
}
_ => {
editor.clear_command_buffer();
}
}
}
}
// === MODE TRANSITIONS WITH AUTOMATIC CURSOR MANAGEMENT ===
(AppMode::ReadOnly, KeyCode::Char('i'), _) => {
editor.enter_edit_mode(); // 🎯 Automatic: cursor becomes bar |
@@ -628,22 +646,6 @@ async fn handle_key_press(
editor.clear_command_buffer();
}
// Escape: Exit any mode back to normal (and cancel suggestions)
(_, KeyCode::Esc, _) => {
match mode {
AppMode::Edit => {
editor.exit_edit_mode(); // Exit insert mode (suggestions auto-cancelled)
}
AppMode::Highlight => {
editor.exit_visual_mode(); // Exit visual mode
}
_ => {
// Already in normal mode, just clear command buffer
editor.clear_command_buffer();
}
}
}
// === CURSOR MANAGEMENT DEMONSTRATION ===
(AppMode::ReadOnly, KeyCode::F(1), _) => {
editor.demo_manual_cursor_control()?;
@@ -669,37 +671,21 @@ async fn handle_key_press(
}
(AppMode::ReadOnly | AppMode::Highlight, KeyCode::Char('j'), _)
| (AppMode::ReadOnly | AppMode::Highlight, KeyCode::Down, _) => {
editor.close_suggestions(); // ⬅ close dropdown
editor.move_down();
let field_names = ["Fruit", "Job", "Language", "Country", "Color"];
let field_name = field_names.get(editor.current_field()).unwrap_or(&"Field");
editor.set_debug_message(format!("↓ moved to {} field", field_name));
editor.clear_command_buffer();
// Auto-show suggestions when entering a suggestion-enabled field with existing text
if editor.data_provider().supports_suggestions(editor.current_field()) {
let current_text = editor.current_text();
if !current_text.is_empty() {
let _ = editor.trigger_suggestions(suggestions_provider).await;
editor.update_inline_completion();
}
}
}
(AppMode::ReadOnly | AppMode::Highlight, KeyCode::Char('k'), _)
| (AppMode::ReadOnly | AppMode::Highlight, KeyCode::Up, _) => {
editor.close_suggestions(); // ⬅ close dropdown
editor.move_up();
let field_names = ["Fruit", "Job", "Language", "Country", "Color"];
let field_name = field_names.get(editor.current_field()).unwrap_or(&"Field");
editor.set_debug_message(format!("↑ moved to {} field", field_name));
editor.clear_command_buffer();
// Auto-show suggestions when entering a suggestion-enabled field with existing text
if editor.data_provider().supports_suggestions(editor.current_field()) {
let current_text = editor.current_text();
if !current_text.is_empty() {
let _ = editor.trigger_suggestions(suggestions_provider).await;
editor.update_inline_completion();
}
}
}
// Word movement
@@ -765,9 +751,11 @@ async fn handle_key_press(
editor.move_right();
}
(AppMode::Edit, KeyCode::Up, _) => {
editor.close_suggestions();
editor.move_up();
}
(AppMode::Edit, KeyCode::Down, _) => {
editor.close_suggestions();
editor.move_down();
}
(AppMode::Edit, KeyCode::Home, _) => {

View File

@@ -134,7 +134,12 @@ impl EditorState {
}
}
pub(crate) fn set_cursor(&mut self, position: usize, max_position: usize, for_edit_mode: bool) {
pub(crate) fn set_cursor(
&mut self,
position: usize,
max_position: usize,
for_edit_mode: bool,
) {
if for_edit_mode {
// Edit mode: can go past end for insertion
self.cursor_pos = position.min(max_position);
@@ -145,6 +150,7 @@ impl EditorState {
self.ideal_cursor_column = self.cursor_pos;
}
/// Legacy internal activation (still used internally if needed)
pub(crate) fn activate_suggestions(&mut self, field_index: usize) {
self.suggestions.is_active = true;
self.suggestions.is_loading = true;
@@ -153,6 +159,7 @@ impl EditorState {
self.suggestions.completion_text = None;
}
/// Legacy internal deactivation
pub(crate) fn deactivate_suggestions(&mut self) {
self.suggestions.is_active = false;
self.suggestions.is_loading = false;
@@ -160,6 +167,24 @@ impl EditorState {
self.suggestions.selected_index = None;
self.suggestions.completion_text = None;
}
/// Explicitly open suggestions — should only be called on Tab
pub(crate) fn open_suggestions(&mut self, field_index: usize) {
self.suggestions.is_active = true;
self.suggestions.is_loading = true;
self.suggestions.active_field = Some(field_index);
self.suggestions.selected_index = None;
self.suggestions.completion_text = None;
}
/// Explicitly close suggestions — should be called on Esc or field change
pub(crate) fn close_suggestions(&mut self) {
self.suggestions.is_active = false;
self.suggestions.is_loading = false;
self.suggestions.active_field = None;
self.suggestions.selected_index = None;
self.suggestions.completion_text = None;
}
}
impl Default for EditorState {

View File

@@ -152,6 +152,22 @@ impl<D: DataProvider> FormEditor<D> {
&self.ui_state
}
/// Mutable access to UI state for internal crate use only.
pub(crate) fn ui_state_mut(&mut self) -> &mut EditorState {
&mut self.ui_state
}
/// Open the suggestions UI for `field_index` (UI-only; does not fetch).
pub fn open_suggestions(&mut self, field_index: usize) {
self.ui_state.open_suggestions(field_index);
}
/// Close suggestions UI and clear the current suggestion results.
pub fn close_suggestions(&mut self) {
self.ui_state.close_suggestions();
self.suggestions.clear();
}
/// Set external validation state for a field (Feature 5)
#[cfg(feature = "validation")]
pub fn set_external_validation(