working autocomplete now, with backwards deprecation

This commit is contained in:
Priec
2025-07-31 22:44:21 +02:00
parent c594c35b37
commit 8f99aa79ec
5 changed files with 59 additions and 45 deletions

View File

@@ -8,18 +8,18 @@ use anyhow::Result;
/// Enhanced execute function for states that support autocomplete
/// This is the main entry point for autocomplete-aware canvas execution
///
///
/// Use this instead of canvas::execute() if you want autocomplete behavior:
/// ```rust
/// execute_with_autocomplete(action, &mut state).await?;
/// ```
pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>(
pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState + Send>(
action: CanvasAction,
state: &mut S,
) -> Result<ActionResult> {
match &action {
// === AUTOCOMPLETE-SPECIFIC ACTIONS ===
CanvasAction::TriggerAutocomplete => {
if state.supports_autocomplete(state.current_field()) {
state.trigger_autocomplete_suggestions().await;
@@ -61,7 +61,7 @@ pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>
}
// === TEXT INSERTION WITH AUTO-TRIGGER ===
CanvasAction::InsertChar(_) => {
// First, execute the character insertion normally
let result = execute(action, state).await?;
@@ -75,7 +75,7 @@ pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>
}
// === NAVIGATION/EDITING ACTIONS (clear autocomplete first) ===
CanvasAction::MoveLeft | CanvasAction::MoveRight |
CanvasAction::MoveUp | CanvasAction::MoveDown |
CanvasAction::NextField | CanvasAction::PrevField |
@@ -84,13 +84,13 @@ pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>
if state.is_autocomplete_active() {
state.clear_autocomplete_suggestions();
}
// Execute the action normally
execute(action, state).await
}
// === ALL OTHER ACTIONS (normal execution) ===
_ => {
// For all other actions, just execute normally
execute(action, state).await
@@ -99,7 +99,7 @@ pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>
}
/// Helper function to integrate autocomplete actions with CanvasState.handle_feature_action()
///
///
/// Use this in your CanvasState implementation like this:
/// ```rust
/// fn handle_feature_action(&mut self, action: &CanvasAction, context: &ActionContext) -> Option<String> {
@@ -107,12 +107,12 @@ pub async fn execute_with_autocomplete<S: CanvasState + AutocompleteCanvasState>
/// if let Some(result) = handle_autocomplete_feature_action(action, self) {
/// return Some(result);
/// }
///
///
/// // Handle your other custom actions...
/// None
/// }
/// ```
pub fn handle_autocomplete_feature_action<S: CanvasState + AutocompleteCanvasState>(
pub fn handle_autocomplete_feature_action<S: CanvasState + AutocompleteCanvasState + Send>(
action: &CanvasAction,
state: &S,
) -> Option<String> {
@@ -160,7 +160,7 @@ pub fn handle_autocomplete_feature_action<S: CanvasState + AutocompleteCanvasSta
/// Legacy compatibility function - kept for backward compatibility
/// This is the old function signature, now it just wraps the new system
#[deprecated(note = "Use execute_with_autocomplete instead")]
pub async fn execute_canvas_action_with_autocomplete<S: CanvasState + AutocompleteCanvasState>(
pub async fn execute_canvas_action_with_autocomplete<S: CanvasState + AutocompleteCanvasState + Send>(
action: CanvasAction,
state: &mut S,
_ideal_cursor_column: &mut usize, // Ignored - new system manages this internally

View File

@@ -1,17 +1,19 @@
// src/autocomplete/state.rs
use crate::canvas::state::CanvasState;
use async_trait::async_trait;
/// OPTIONAL extension trait for states that want rich autocomplete functionality.
/// Only implement this if you need the new autocomplete features.
///
///
/// # User Workflow:
/// 1. User presses trigger key (Tab, Ctrl+K, etc.)
/// 2. User's key mapping calls CanvasAction::TriggerAutocomplete
/// 2. User's key mapping calls CanvasAction::TriggerAutocomplete
/// 3. Library calls your trigger_autocomplete_suggestions() method
/// 4. You implement async fetching logic in that method
/// 5. You call set_autocomplete_suggestions() with results
/// 6. Library manages UI state and navigation
#[async_trait]
pub trait AutocompleteCanvasState: CanvasState {
/// Associated type for suggestion data (e.g., Hit, String, CustomType)
type SuggestionData: Clone + Send + 'static;
@@ -92,34 +94,39 @@ pub trait AutocompleteCanvasState: CanvasState {
fn should_trigger_autocomplete(&self) -> bool {
let current_input = self.get_current_input();
let current_field = self.current_field();
self.supports_autocomplete(current_field) &&
self.supports_autocomplete(current_field) &&
current_input.len() >= 2 && // Default: trigger after 2 chars
!self.is_autocomplete_active()
}
/// **USER MUST IMPLEMENT**: Trigger autocomplete suggestions (async)
/// This is where you implement your API calls, caching, etc.
///
///
/// # Example Implementation:
/// ```rust
/// async fn trigger_autocomplete_suggestions(&mut self) {
/// self.activate_autocomplete(); // Show loading state
/// #[async_trait]
/// impl AutocompleteCanvasState for MyState {
/// type SuggestionData = MyData;
///
/// let query = self.get_current_input().to_string();
/// let suggestions = my_api.search(&query).await.unwrap_or_default();
///
/// self.set_autocomplete_suggestions(suggestions);
/// async fn trigger_autocomplete_suggestions(&mut self) {
/// self.activate_autocomplete(); // Show loading state
///
/// let query = self.get_current_input().to_string();
/// let suggestions = my_api.search(&query).await.unwrap_or_default();
///
/// self.set_autocomplete_suggestions(suggestions);
/// }
/// }
/// ```
async fn trigger_autocomplete_suggestions(&mut self) {
// Activate autocomplete UI
self.activate_autocomplete();
// Default: just show loading state
// User should override this to do actual async fetching
self.set_autocomplete_loading(true);
// In a real implementation, you'd:
// 1. Get current input: let query = self.get_current_input();
// 2. Make API call: let results = api.search(query).await;
@@ -157,7 +164,7 @@ pub trait AutocompleteCanvasState: CanvasState {
// Apply the value to current field
*self.get_current_input_mut() = suggestion.value_to_store.clone();
self.set_has_unsaved_changes(true);
// Clear autocomplete
self.clear_autocomplete_suggestions();
}