different structure of the library

This commit is contained in:
Priec
2025-07-29 23:04:48 +02:00
parent 46a85e4b4a
commit 05bb84fc98
18 changed files with 146 additions and 142 deletions

View File

@@ -1,4 +1,4 @@
// canvas/src/gui/autocomplete.rs // canvas/src/autocomplete/gui.rs
#[cfg(feature = "gui")] #[cfg(feature = "gui")]
use ratatui::{ use ratatui::{
@@ -9,7 +9,9 @@ use ratatui::{
}; };
use crate::autocomplete::AutocompleteState; use crate::autocomplete::AutocompleteState;
use super::theme::CanvasTheme;
#[cfg(feature = "gui")]
use crate::canvas::theme::CanvasTheme;
#[cfg(feature = "gui")] #[cfg(feature = "gui")]
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;

View File

@@ -0,0 +1,8 @@
// src/autocomplete/mod.rs
pub mod types;
pub mod gui;
pub mod state; // Add this line
// Re-export autocomplete types
pub use types::{SuggestionItem, AutocompleteState};
pub use state::AutocompleteCanvasState; // Add this line

View File

@@ -1,100 +1,6 @@
// canvas/src/state.rs // canvas/src/state.rs
use crate::actions::CanvasAction; use crate::canvas::state::CanvasState;
/// Context passed to feature-specific action handlers
#[derive(Debug)]
pub struct ActionContext {
pub key_code: Option<crossterm::event::KeyCode>, // Kept for backwards compatibility
pub ideal_cursor_column: usize,
pub current_input: String,
pub current_field: usize,
}
/// Core trait that any form-like state must implement to work with the canvas system.
/// This enables the same mode behaviors (edit, read-only, highlight) to work across
/// any implementation - login forms, data entry forms, configuration screens, etc.
pub trait CanvasState {
// --- Core Navigation ---
fn current_field(&self) -> usize;
fn current_cursor_pos(&self) -> usize;
fn set_current_field(&mut self, index: usize);
fn set_current_cursor_pos(&mut self, pos: usize);
// --- Data Access ---
fn get_current_input(&self) -> &str;
fn get_current_input_mut(&mut self) -> &mut String;
fn inputs(&self) -> Vec<&String>;
fn fields(&self) -> Vec<&str>;
// --- State Management ---
fn has_unsaved_changes(&self) -> bool;
fn set_has_unsaved_changes(&mut self, changed: bool);
// --- LEGACY AUTOCOMPLETE SUPPORT (for backwards compatibility) ---
/// Legacy suggestion support (deprecated - use AutocompleteCanvasState for rich features)
fn get_suggestions(&self) -> Option<&[String]> {
None
}
/// Legacy selected suggestion index (deprecated)
fn get_selected_suggestion_index(&self) -> Option<usize> {
None
}
/// Legacy suggestion index setter (deprecated)
fn set_selected_suggestion_index(&mut self, _index: Option<usize>) {
// Default: no-op
}
/// Legacy activate suggestions (deprecated)
fn activate_suggestions(&mut self, _suggestions: Vec<String>) {
// Default: no-op
}
/// Legacy deactivate suggestions (deprecated)
fn deactivate_suggestions(&mut self) {
// Default: no-op
}
// --- Feature-specific action handling ---
/// Feature-specific action handling (NEW: Type-safe)
fn handle_feature_action(&mut self, _action: &CanvasAction, _context: &ActionContext) -> Option<String> {
None // Default: no feature-specific handling
}
/// Legacy string-based action handling (for backwards compatibility)
fn handle_feature_action_legacy(&mut self, action: &str, context: &ActionContext) -> Option<String> {
// Convert string to typed action and delegate
let typed_action = match action {
"insert_char" => {
// This is tricky - we need the char from the KeyCode in context
if let Some(crossterm::event::KeyCode::Char(c)) = context.key_code {
CanvasAction::InsertChar(c)
} else {
CanvasAction::Custom(action.to_string())
}
}
_ => CanvasAction::from_string(action),
};
self.handle_feature_action(&typed_action, context)
}
// --- Display Overrides (for links, computed values, etc.) ---
fn get_display_value_for_field(&self, index: usize) -> &str {
self.inputs()
.get(index)
.map(|s| s.as_str())
.unwrap_or("")
}
fn has_display_override(&self, _index: usize) -> bool {
false
}
}
/// OPTIONAL extension trait for states that want rich autocomplete functionality. /// OPTIONAL extension trait for states that want rich autocomplete functionality.
/// Only implement this if you need the new autocomplete features. /// Only implement this if you need the new autocomplete features.

View File

@@ -1,7 +1,8 @@
// canvas/src/actions/edit.rs // canvas/src/actions/edit.rs
use crate::state::{CanvasState, AutocompleteCanvasState, ActionContext}; use crate::canvas::state::{CanvasState, ActionContext};
use crate::actions::types::{CanvasAction, ActionResult}; use crate::autocomplete::state::AutocompleteCanvasState;
use crate::canvas::actions::types::{CanvasAction, ActionResult};
use crossterm::event::{KeyCode, KeyEvent}; use crossterm::event::{KeyCode, KeyEvent};
use anyhow::Result; use anyhow::Result;

View File

@@ -1,4 +1,4 @@
// canvas/src/gui/canvas.rs // canvas/src/canvas/gui.rs
#[cfg(feature = "gui")] #[cfg(feature = "gui")]
use ratatui::{ use ratatui::{
@@ -9,9 +9,11 @@ use ratatui::{
Frame, Frame,
}; };
use crate::state::CanvasState; use crate::canvas::state::CanvasState;
use crate::modes::HighlightState; use crate::canvas::modes::HighlightState;
use super::theme::CanvasTheme;
#[cfg(feature = "gui")]
use crate::canvas::theme::CanvasTheme;
#[cfg(feature = "gui")] #[cfg(feature = "gui")]
use std::cmp::{max, min}; use std::cmp::{max, min};

14
canvas/src/canvas/mod.rs Normal file
View File

@@ -0,0 +1,14 @@
// src/canvas/mod.rs
pub mod actions;
pub mod modes;
pub mod gui;
pub mod theme;
pub mod state; // Add this line
// Re-export commonly used canvas types
pub use actions::{CanvasAction, ActionResult};
pub use modes::{AppMode, ModeManager, HighlightState};
pub use state::{CanvasState, ActionContext}; // Add this line
#[cfg(feature = "gui")]
pub use theme::CanvasTheme;

View File

@@ -0,0 +1,97 @@
// canvas/src/state.rs
use crate::canvas::actions::CanvasAction;
/// Context passed to feature-specific action handlers
#[derive(Debug)]
pub struct ActionContext {
pub key_code: Option<crossterm::event::KeyCode>, // Kept for backwards compatibility
pub ideal_cursor_column: usize,
pub current_input: String,
pub current_field: usize,
}
/// Core trait that any form-like state must implement to work with the canvas system.
/// This enables the same mode behaviors (edit, read-only, highlight) to work across
/// any implementation - login forms, data entry forms, configuration screens, etc.
pub trait CanvasState {
// --- Core Navigation ---
fn current_field(&self) -> usize;
fn current_cursor_pos(&self) -> usize;
fn set_current_field(&mut self, index: usize);
fn set_current_cursor_pos(&mut self, pos: usize);
// --- Data Access ---
fn get_current_input(&self) -> &str;
fn get_current_input_mut(&mut self) -> &mut String;
fn inputs(&self) -> Vec<&String>;
fn fields(&self) -> Vec<&str>;
// --- State Management ---
fn has_unsaved_changes(&self) -> bool;
fn set_has_unsaved_changes(&mut self, changed: bool);
// --- LEGACY AUTOCOMPLETE SUPPORT (for backwards compatibility) ---
/// Legacy suggestion support (deprecated - use AutocompleteCanvasState for rich features)
fn get_suggestions(&self) -> Option<&[String]> {
None
}
/// Legacy selected suggestion index (deprecated)
fn get_selected_suggestion_index(&self) -> Option<usize> {
None
}
/// Legacy suggestion index setter (deprecated)
fn set_selected_suggestion_index(&mut self, _index: Option<usize>) {
// Default: no-op
}
/// Legacy activate suggestions (deprecated)
fn activate_suggestions(&mut self, _suggestions: Vec<String>) {
// Default: no-op
}
/// Legacy deactivate suggestions (deprecated)
fn deactivate_suggestions(&mut self) {
// Default: no-op
}
// --- Feature-specific action handling ---
/// Feature-specific action handling (NEW: Type-safe)
fn handle_feature_action(&mut self, _action: &CanvasAction, _context: &ActionContext) -> Option<String> {
None // Default: no feature-specific handling
}
/// Legacy string-based action handling (for backwards compatibility)
fn handle_feature_action_legacy(&mut self, action: &str, context: &ActionContext) -> Option<String> {
// Convert string to typed action and delegate
let typed_action = match action {
"insert_char" => {
// This is tricky - we need the char from the KeyCode in context
if let Some(crossterm::event::KeyCode::Char(c)) = context.key_code {
CanvasAction::InsertChar(c)
} else {
CanvasAction::Custom(action.to_string())
}
}
_ => CanvasAction::from_string(action),
};
self.handle_feature_action(&typed_action, context)
}
// --- Display Overrides (for links, computed values, etc.) ---
fn get_display_value_for_field(&self, index: usize) -> &str {
self.inputs()
.get(index)
.map(|s| s.as_str())
.unwrap_or("")
}
fn has_display_override(&self, _index: usize) -> bool {
false
}
}

View File

@@ -476,5 +476,5 @@ impl CanvasConfig {
} }
// Re-export for convenience // Re-export for convenience
pub use crate::actions::CanvasAction; pub use crate::canvas::actions::CanvasAction;
pub use crate::dispatcher::ActionDispatcher; pub use crate::dispatcher::ActionDispatcher;

View File

@@ -1,7 +1,7 @@
// canvas/src/dispatcher.rs // canvas/src/dispatcher.rs
use crate::state::CanvasState; use crate::canvas::state::CanvasState;
use crate::actions::{CanvasAction, ActionResult, execute_canvas_action}; use crate::canvas::actions::{CanvasAction, ActionResult, execute_canvas_action};
/// High-level action dispatcher that coordinates between different action types /// High-level action dispatcher that coordinates between different action types
pub struct ActionDispatcher; pub struct ActionDispatcher;

View File

@@ -1,20 +0,0 @@
// canvas/src/gui/mod.rs
#[cfg(feature = "gui")]
pub mod canvas;
#[cfg(feature = "gui")]
pub mod autocomplete;
#[cfg(feature = "gui")]
pub mod theme;
// Export the separate rendering functions
#[cfg(feature = "gui")]
pub use canvas::render_canvas;
#[cfg(feature = "gui")]
pub use autocomplete::render_autocomplete_dropdown;
#[cfg(feature = "gui")]
pub use theme::CanvasTheme;

View File

@@ -1,25 +1,19 @@
// canvas/src/lib.rs // src/lib.rs
pub mod canvas;
pub mod actions; pub mod autocomplete;
pub mod config; pub mod config;
pub mod dispatcher; pub mod dispatcher;
pub mod state;
pub mod suggestions; // Keep for backwards compatibility pub mod suggestions; // Keep for backwards compatibility
pub mod autocomplete; // NEW: Core autocomplete functionality
pub mod modes; // Re-export from modules
pub use canvas::{CanvasAction, ActionResult, AppMode, ModeManager, HighlightState};
#[cfg(feature = "gui")] #[cfg(feature = "gui")]
pub mod gui; pub use canvas::CanvasTheme;
// Re-export commonly used types pub use autocomplete::{SuggestionItem, AutocompleteState};
pub use actions::{CanvasAction, ActionResult};
pub use dispatcher::ActionDispatcher; pub use dispatcher::ActionDispatcher;
pub use state::{CanvasState, ActionContext}; pub use canvas::state::{CanvasState, ActionContext}; // Fixed path
pub use autocomplete::{SuggestionItem, AutocompleteState}; // NEW
pub use modes::{AppMode, ModeManager, HighlightState};
#[cfg(feature = "gui")] // Backwards compatibility
pub use gui::{render_canvas, CanvasTheme};
// Keep backwards compatibility exports
pub use suggestions::SuggestionState; pub use suggestions::SuggestionState;