fixing examples

This commit is contained in:
Priec
2025-08-07 13:51:59 +02:00
parent d601134535
commit 5b2e0e976f
6 changed files with 149 additions and 71 deletions

View File

@@ -43,7 +43,7 @@ path = "examples/suggestions.rs"
[[example]] [[example]]
name = "canvas_gui_demo" name = "canvas_gui_demo"
required-features = ["gui"] required-features = ["gui", "cursor-style"]
path = "examples/canvas_gui_demo.rs" path = "examples/canvas_gui_demo.rs"
[[example]] [[example]]

View File

@@ -1,7 +1,7 @@
// examples/validation_1.rs // examples/validation_1.rs
//! Demonstrates field validation with the canvas library //! Demonstrates field validation with the canvas library
//! //!
//! This example REQUIRES the `validation` feature to compile. //! This example REQUIRES the `validation` and `cursor-style` features to compile.
//! //!
//! Run with: //! Run with:
//! cargo run --example validation_1 --features "gui,validation" //! cargo run --example validation_1 --features "gui,validation"
@@ -10,10 +10,10 @@
//! cargo run --example validation_1 --features "gui" //! cargo run --example validation_1 --features "gui"
// REQUIRE validation feature - example won't compile without it // REQUIRE validation feature - example won't compile without it
#[cfg(not(feature = "validation"))] #[cfg(not(all(feature = "validation", feature = "cursor-style")))]
compile_error!( compile_error!(
"This example requires the 'validation' feature. \ "This example requires the 'validation' and 'cursor-style' features. \
Run with: cargo run --example validation_1 --features \"gui,validation\"" Run with: cargo run --example validation_1 --features \"gui,validation,cursor-style\""
); );
use std::io; use std::io;
@@ -39,6 +39,7 @@ use canvas::{
canvas::{ canvas::{
gui::render_canvas_default, gui::render_canvas_default,
modes::AppMode, modes::AppMode,
CursorManager,
}, },
DataProvider, FormEditor, DataProvider, FormEditor,
ValidationConfig, ValidationConfigBuilder, CharacterLimits, ValidationResult, ValidationConfig, ValidationConfigBuilder, CharacterLimits, ValidationResult,
@@ -269,18 +270,21 @@ impl<D: DataProvider> ValidationFormEditor<D> {
// === MODE TRANSITIONS === // === MODE TRANSITIONS ===
fn enter_edit_mode(&mut self) { fn enter_edit_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_edit_mode(); self.editor.enter_edit_mode();
self.debug_message = "✏️ INSERT MODE - Type to test validation".to_string(); self.debug_message = "✏️ INSERT MODE - Cursor: Steady Bar | - Type to test validation".to_string();
} }
fn enter_append_mode(&mut self) { fn enter_append_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_append_mode(); self.editor.enter_append_mode();
self.debug_message = "✏️ INSERT (append) - Validation active".to_string(); self.debug_message = "✏️ INSERT (append) - Cursor: Steady Bar | - Validation active".to_string();
} }
fn exit_edit_mode(&mut self) { fn exit_edit_mode(&mut self) {
// Library will automatically update cursor to block █ in normal mode
self.editor.exit_edit_mode(); self.editor.exit_edit_mode();
self.debug_message = "🔒 NORMAL MODE - Press 'v' to validate current field".to_string(); self.debug_message = "🔒 NORMAL MODE - Cursor: Steady Block █ - Press 'v' to validate current field".to_string();
self.update_field_validation_status(); self.update_field_validation_status();
} }
@@ -362,6 +366,7 @@ impl<D: DataProvider> ValidationFormEditor<D> {
} }
fn set_mode(&mut self, mode: AppMode) { fn set_mode(&mut self, mode: AppMode) {
// Library automatically updates cursor for the mode
self.editor.set_mode(mode); self.editor.set_mode(mode);
} }
@@ -694,9 +699,9 @@ fn render_validation_status(
// Status bar with validation information // Status bar with validation information
let mode_text = match editor.mode() { let mode_text = match editor.mode() {
AppMode::Edit => "INSERT", AppMode::Edit => "INSERT | (bar cursor)",
AppMode::ReadOnly => "NORMAL", AppMode::ReadOnly => "NORMAL █ (block cursor)",
_ => "OTHER", _ => "NORMAL █ (block cursor)",
}; };
let validation_status = editor.get_validation_status(); let validation_status = editor.get_validation_status();
@@ -765,21 +770,21 @@ fn render_validation_status(
// Enhanced help text // Enhanced help text
let help_text = match editor.mode() { let help_text = match editor.mode() {
AppMode::ReadOnly => { AppMode::ReadOnly => {
"🔍 VALIDATION DEMO: Different fields have different limits!\n\ "🎯 CURSOR-STYLE: Normal █ | Insert |\n\
Fields with MINIMUM requirements will block field switching if too short!\n\ 🔍 VALIDATION: Different fields have different limits (some block field switching)!\n\
Movement: hjkl/arrows=move, Tab/Shift+Tab=fields\n\ Movement: hjkl/arrows=move, Tab/Shift+Tab=fields\n\
Edit: i/a/A=insert modes, Esc=normal\n\ Edit: i/a/A=insert modes, Esc=normal\n\
Validation: v=validate current, V=validate all, c=clear results, F1=toggle\n\ Validation: v=validate current, V=validate all, c=clear results, F1=toggle\n\
?=info, Ctrl+C/Ctrl+Q=quit" ?=info, Ctrl+C/Ctrl+Q=quit"
} }
AppMode::Edit => { AppMode::Edit => {
"✏️ INSERT MODE - Type to test validation limits!\n\ "🎯 INSERT MODE - Cursor: | (bar)\n\
Some fields have MINIMUM character requirements!\n\ 🔍 Type to test validation limits (some fields have MIN requirements)!\n\
Try typing 1-2 chars in Password/ID/Comment fields, then try to switch!\n\ Try typing 1-2 chars in Password/ID/Comment fields, then try to switch!\n\
arrows=move, Backspace/Del=delete, Esc=normal, Tab=next field\n\ arrows=move, Backspace/Del=delete, Esc=normal, Tab=next field\n\
Field switching may be BLOCKED if minimum requirements not met!" Field switching may be BLOCKED if minimum requirements not met!"
} }
_ => "🔍 Validation Demo Active!" _ => "🎯 Watch the cursor change automatically while validating!"
}; };
let help = Paragraph::new(help_text) let help = Paragraph::new(help_text)
@@ -810,10 +815,20 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let data = ValidationDemoData::new(); let data = ValidationDemoData::new();
let editor = ValidationFormEditor::new(data); let mut editor = ValidationFormEditor::new(data);
// Initialize with normal mode - library automatically sets block cursor
editor.set_mode(AppMode::ReadOnly);
// Demonstrate that CursorManager is available and working
CursorManager::update_for_mode(AppMode::ReadOnly)?;
let res = run_app(&mut terminal, editor); let res = run_app(&mut terminal, editor);
// Library automatically resets cursor on FormEditor::drop()
// But we can also manually reset if needed
CursorManager::reset()?;
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
terminal.backend_mut(), terminal.backend_mut(),

View File

@@ -4,13 +4,13 @@
//! This example showcases the full potential of the pattern validation system //! This example showcases the full potential of the pattern validation system
//! with creative real-world scenarios and edge cases. //! with creative real-world scenarios and edge cases.
//! //!
//! Run with: cargo run --example validation_advanced_patterns --features "validation,gui" //! Run with: cargo run --example validation_advanced_patterns --features "validation,gui,cursor-style"
// REQUIRE validation and gui features // REQUIRE validation, gui and cursor-style features
#[cfg(not(all(feature = "validation", feature = "gui")))] #[cfg(not(all(feature = "validation", feature = "gui", feature = "cursor-style")))]
compile_error!( compile_error!(
"This example requires the 'validation' and 'gui' features. \ "This example requires the 'validation', 'gui' and 'cursor-style' features. \
Run with: cargo run --example validation_advanced_patterns --features \"validation,gui\"" Run with: cargo run --example validation_advanced_patterns --features \"validation,gui,cursor-style\""
); );
use std::io; use std::io;
@@ -38,6 +38,7 @@ use canvas::{
canvas::{ canvas::{
gui::render_canvas_default, gui::render_canvas_default,
modes::AppMode, modes::AppMode,
CursorManager,
}, },
DataProvider, FormEditor, DataProvider, FormEditor,
ValidationConfig, ValidationConfigBuilder, PatternFilters, PositionFilter, PositionRange, CharacterFilter, ValidationConfig, ValidationConfigBuilder, PatternFilters, PositionFilter, PositionRange, CharacterFilter,
@@ -107,18 +108,21 @@ impl<D: DataProvider> AdvancedPatternFormEditor<D> {
fn move_line_end(&mut self) { self.editor.move_line_end(); } fn move_line_end(&mut self) { self.editor.move_line_end(); }
fn enter_edit_mode(&mut self) { fn enter_edit_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_edit_mode(); self.editor.enter_edit_mode();
self.debug_message = "✏️ INSERT MODE - Testing advanced pattern validation".to_string(); self.debug_message = "✏️ INSERT MODE - Cursor: Steady Bar | - Testing advanced pattern validation".to_string();
} }
fn enter_append_mode(&mut self) { fn enter_append_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_append_mode(); self.editor.enter_append_mode();
self.debug_message = "✏️ INSERT (append) - Advanced patterns active".to_string(); self.debug_message = "✏️ INSERT (append) - Cursor: Steady Bar | - Advanced patterns active".to_string();
} }
fn exit_edit_mode(&mut self) { fn exit_edit_mode(&mut self) {
// Library will automatically update cursor to block █ in normal mode
self.editor.exit_edit_mode(); self.editor.exit_edit_mode();
self.debug_message = "🔒 NORMAL MODE".to_string(); self.debug_message = "🔒 NORMAL MODE - Cursor: Steady Block █".to_string();
self.update_field_validation_status(); self.update_field_validation_status();
} }
@@ -522,9 +526,9 @@ fn render_advanced_validation_status(
// Status bar // Status bar
let mode_text = match editor.mode() { let mode_text = match editor.mode() {
AppMode::Edit => "INSERT", AppMode::Edit => "INSERT | (bar cursor)",
AppMode::ReadOnly => "NORMAL", AppMode::ReadOnly => "NORMAL █ (block cursor)",
_ => "OTHER", _ => "NORMAL █ (block cursor)",
}; };
let validation_status = editor.get_validation_status(); let validation_status = editor.get_validation_status();
@@ -613,6 +617,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 Canvas Advanced Pattern Validation Demo"); println!("🚀 Canvas Advanced Pattern Validation Demo");
println!("✅ validation feature: ENABLED"); println!("✅ validation feature: ENABLED");
println!("✅ gui feature: ENABLED"); println!("✅ gui feature: ENABLED");
println!("✅ cursor-style feature: ENABLED");
println!("🎯 Advanced pattern filtering: ACTIVE"); println!("🎯 Advanced pattern filtering: ACTIVE");
println!("🧪 Edge cases and complex patterns: READY"); println!("🧪 Edge cases and complex patterns: READY");
println!("💡 Each field showcases different validation capabilities!"); println!("💡 Each field showcases different validation capabilities!");
@@ -625,10 +630,20 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let data = AdvancedPatternData::new(); let data = AdvancedPatternData::new();
let editor = AdvancedPatternFormEditor::new(data); let mut editor = AdvancedPatternFormEditor::new(data);
// Initialize with normal mode - library automatically sets block cursor
editor.set_mode(AppMode::ReadOnly);
// Demonstrate that CursorManager is available and working
CursorManager::update_for_mode(AppMode::ReadOnly)?;
let res = run_app(&mut terminal, editor); let res = run_app(&mut terminal, editor);
// Library automatically resets cursor on FormEditor::drop()
// But we can also manually reset if needed
CursorManager::reset()?;
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
terminal.backend_mut(), terminal.backend_mut(),

View File

@@ -18,13 +18,13 @@
//! Each mask's input position count EXACTLY matches its character limit to prevent //! Each mask's input position count EXACTLY matches its character limit to prevent
//! the critical bug where users can type more characters than they can see. //! the critical bug where users can type more characters than they can see.
//! //!
//! Run with: cargo run --example validation_3 --features "gui,validation" //! Run with: cargo run --example validation_3 --features "gui,validation,cursor-style"
// REQUIRE validation and gui features for mask functionality // REQUIRE validation, gui and cursor-style features for mask functionality
#[cfg(not(all(feature = "validation", feature = "gui")))] #[cfg(not(all(feature = "validation", feature = "gui", feature = "cursor-style")))]
compile_error!( compile_error!(
"This example requires the 'validation' and 'gui' features. \ "This example requires the 'validation', 'gui' and 'cursor-style' features. \
Run with: cargo run --example validation_3 --features \"gui,validation\"" Run with: cargo run --example validation_3 --features \"gui,validation,cursor-style\""
); );
use std::io; use std::io;
@@ -50,6 +50,7 @@ use canvas::{
canvas::{ canvas::{
gui::render_canvas_default, gui::render_canvas_default,
modes::AppMode, modes::AppMode,
CursorManager,
}, },
DataProvider, FormEditor, DataProvider, FormEditor,
ValidationConfig, ValidationConfigBuilder, DisplayMask, ValidationConfig, ValidationConfigBuilder, DisplayMask,
@@ -183,18 +184,21 @@ impl<D: DataProvider> MaskDemoFormEditor<D> {
// === MODE TRANSITIONS === // === MODE TRANSITIONS ===
fn enter_edit_mode(&mut self) { fn enter_edit_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_edit_mode(); self.editor.enter_edit_mode();
self.debug_message = "✏️ INSERT MODE - Type to see mask formatting in real-time".to_string(); self.debug_message = "✏️ INSERT MODE - Cursor: Steady Bar | - Type to see mask formatting in real-time".to_string();
} }
fn enter_append_mode(&mut self) { fn enter_append_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_append_mode(); self.editor.enter_append_mode();
self.debug_message = "✏️ INSERT (append) - Mask formatting active".to_string(); self.debug_message = "✏️ INSERT (append) - Cursor: Steady Bar | - Mask formatting active".to_string();
} }
fn exit_edit_mode(&mut self) { fn exit_edit_mode(&mut self) {
// Library will automatically update cursor to block █ in normal mode
self.editor.exit_edit_mode(); self.editor.exit_edit_mode();
self.debug_message = "🔒 NORMAL MODE - Press 'r' to see raw data, 'm' for mask info".to_string(); self.debug_message = "🔒 NORMAL MODE - Cursor: Steady Block █ - Press 'r' to see raw data, 'm' for mask info".to_string();
} }
fn insert_char(&mut self, ch: char) -> anyhow::Result<()> { fn insert_char(&mut self, ch: char) -> anyhow::Result<()> {
@@ -236,7 +240,10 @@ impl<D: DataProvider> MaskDemoFormEditor<D> {
fn current_text(&self) -> &str { self.editor.current_text() } fn current_text(&self) -> &str { self.editor.current_text() }
fn data_provider(&self) -> &D { self.editor.data_provider() } fn data_provider(&self) -> &D { self.editor.data_provider() }
fn ui_state(&self) -> &canvas::EditorState { self.editor.ui_state() } fn ui_state(&self) -> &canvas::EditorState { self.editor.ui_state() }
fn set_mode(&mut self, mode: AppMode) { self.editor.set_mode(mode); } fn set_mode(&mut self, mode: AppMode) {
// Library automatically updates cursor for the mode
self.editor.set_mode(mode);
}
fn next_field(&mut self) { fn next_field(&mut self) {
match self.editor.next_field() { match self.editor.next_field() {
@@ -582,9 +589,9 @@ fn render_mask_status(
// Status bar with mask information // Status bar with mask information
let mode_text = match editor.mode() { let mode_text = match editor.mode() {
AppMode::Edit => "INSERT", AppMode::Edit => "INSERT | (bar cursor)",
AppMode::ReadOnly => "NORMAL", AppMode::ReadOnly => "NORMAL █ (block cursor)",
_ => "OTHER", _ => "NORMAL █ (block cursor)",
}; };
let mask_status = editor.get_mask_status(); let mask_status = editor.get_mask_status();
@@ -634,7 +641,8 @@ fn render_mask_status(
// Enhanced help text // Enhanced help text
let help_text = match editor.mode() { let help_text = match editor.mode() {
AppMode::ReadOnly => { AppMode::ReadOnly => {
"🎭 MASK DEMO: See how visual formatting keeps business logic clean!\n\ "🎯 CURSOR-STYLE: Normal █ | Insert |\n\
🎭 MASK DEMO: Visual formatting keeps business logic clean!\n\
\n\ \n\
📱 Try different fields to see various mask patterns:\n\ 📱 Try different fields to see various mask patterns:\n\
• Dynamic vs Template modes • Custom separators • Different input chars\n\ • Dynamic vs Template modes • Custom separators • Different input chars\n\
@@ -644,7 +652,8 @@ fn render_mask_status(
?=detailed info, Ctrl+C=quit" ?=detailed info, Ctrl+C=quit"
} }
AppMode::Edit => { AppMode::Edit => {
"✏️ INSERT MODE - Type to see real-time mask formatting!\n\ "🎯 INSERT MODE - Cursor: | (bar)\n\
✏️ Type to see real-time mask formatting!\n\
\n\ \n\
🔥 Key Features in Action:\n\ 🔥 Key Features in Action:\n\
• Separators auto-appear as you type • Cursor skips over separators\n\ • Separators auto-appear as you type • Cursor skips over separators\n\
@@ -670,6 +679,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("✅ validation feature: ENABLED"); println!("✅ validation feature: ENABLED");
println!("✅ gui feature: ENABLED"); println!("✅ gui feature: ENABLED");
println!("🎭 Display masks: ACTIVE"); println!("🎭 Display masks: ACTIVE");
println!("✅ cursor-style feature: ENABLED");
println!("🔥 Key Benefits Demonstrated:"); println!("🔥 Key Benefits Demonstrated:");
println!(" • Clean separation: Visual formatting ≠ Business logic"); println!(" • Clean separation: Visual formatting ≠ Business logic");
println!(" • User-friendly: Pretty displays with automatic cursor handling"); println!(" • User-friendly: Pretty displays with automatic cursor handling");
@@ -690,7 +700,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let data = MaskDemoData::new(); let data = MaskDemoData::new();
let editor = MaskDemoFormEditor::new(data); let mut editor = MaskDemoFormEditor::new(data);
// Initialize with normal mode - library automatically sets block cursor
editor.set_mode(AppMode::ReadOnly);
// Demonstrate that CursorManager is available and working
CursorManager::update_for_mode(AppMode::ReadOnly)?;
let res = run_app(&mut terminal, editor); let res = run_app(&mut terminal, editor);
@@ -702,6 +718,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
)?; )?;
terminal.show_cursor()?; terminal.show_cursor()?;
// Library automatically resets cursor on FormEditor::drop()
// But we can also manually reset if needed
CursorManager::reset()?;
if let Err(err) = res { if let Err(err) = res {
println!("{:?}", err); println!("{:?}", err);
} }

View File

@@ -13,10 +13,10 @@
#![allow(clippy::needless_return)] #![allow(clippy::needless_return)]
#[cfg(not(all(feature = "validation", feature = "gui")))] #[cfg(not(all(feature = "validation", feature = "gui", feature = "cursor-style")))]
compile_error!( compile_error!(
"This example requires the 'validation' and 'gui' features. \ "This example requires the 'validation', 'gui' and 'cursor-style' features. \
Run with: cargo run --example validation_4 --features \"gui,validation\"" Run with: cargo run --example validation_4 --features \"gui,validation,cursor-style\""
); );
use std::io; use std::io;
@@ -39,7 +39,7 @@ use ratatui::{
}; };
use canvas::{ use canvas::{
canvas::{gui::render_canvas_default, modes::AppMode}, canvas::{gui::render_canvas_default, modes::AppMode, CursorManager},
DataProvider, FormEditor, DataProvider, FormEditor,
ValidationConfig, ValidationConfigBuilder, ValidationConfig, ValidationConfigBuilder,
CustomFormatter, FormattingResult, CustomFormatter, FormattingResult,
@@ -403,21 +403,23 @@ impl<D: DataProvider> EnhancedDemoEditor<D> {
// Delegate methods with enhanced feedback // Delegate methods with enhanced feedback
fn enter_edit_mode(&mut self) { fn enter_edit_mode(&mut self) {
// Library will automatically update cursor to bar | in insert mode
self.editor.enter_edit_mode(); self.editor.enter_edit_mode();
let field_type = self.current_field_type(); let field_type = self.current_field_type();
let rules = self.get_input_rules(); let rules = self.get_input_rules();
self.debug_message = format!("✏️ EDITING {} - {}", field_type, rules); self.debug_message = format!("✏️ INSERT MODE - Cursor: Steady Bar | - {} - {}", field_type, rules);
} }
fn exit_edit_mode(&mut self) { fn exit_edit_mode(&mut self) {
// Library will automatically update cursor to block █ in normal mode
self.editor.exit_edit_mode(); self.editor.exit_edit_mode();
let (raw, display, _, warning) = self.get_current_field_analysis(); let (raw, display, _, warning) = self.get_current_field_analysis();
if let Some(warn) = warning { if let Some(warn) = warning {
self.debug_message = format!("🔒 NORMAL - {} | ⚠️ {}", self.current_field_type(), warn); self.debug_message = format!("🔒 NORMAL - Cursor: Steady Block █ - {} | ⚠️ {}", self.current_field_type(), warn);
} else if raw != display { } else if raw != display {
self.debug_message = format!("🔒 NORMAL - {} formatted successfully", self.current_field_type()); self.debug_message = format!("🔒 NORMAL - Cursor: Steady Block █ - {} formatted successfully", self.current_field_type());
} else { } else {
self.debug_message = "🔒 NORMAL MODE".to_string(); self.debug_message = "🔒 NORMAL MODE - Cursor: Steady Block █".to_string();
} }
} }
@@ -588,9 +590,9 @@ fn render_enhanced_status(
// Status bar // Status bar
let mode_text = match editor.mode() { let mode_text = match editor.mode() {
AppMode::Edit => "INSERT", AppMode::Edit => "INSERT | (bar cursor)",
AppMode::ReadOnly => "NORMAL", AppMode::ReadOnly => "NORMAL █ (block cursor)",
_ => "OTHER", _ => "NORMAL █ (block cursor)",
}; };
let formatter_count = (0..editor.data_provider().field_count()) let formatter_count = (0..editor.data_provider().field_count())
@@ -660,7 +662,8 @@ fn render_enhanced_status(
// Enhanced help // Enhanced help
let help_text = match editor.mode() { let help_text = match editor.mode() {
AppMode::ReadOnly => { AppMode::ReadOnly => {
"🧩 ENHANCED CUSTOM FORMATTER DEMO\n\ "🎯 CURSOR-STYLE: Normal █ | Insert |\n\
🧩 ENHANCED CUSTOM FORMATTER DEMO\n\
\n\ \n\
Try these formatters: Try these formatters:
• PSC: 01001 → 010 01 | Phone: 1234567890 → (123) 456-7890 | Card: 1234567890123456 → 1234 5678 9012 3456 • PSC: 01001 → 010 01 | Phone: 1234567890 → (123) 456-7890 | Card: 1234567890123456 → 1234 5678 9012 3456
@@ -671,7 +674,8 @@ fn render_enhanced_status(
Ctrl+C/F10=quit" Ctrl+C/F10=quit"
} }
AppMode::Edit => { AppMode::Edit => {
"✏️ INSERT MODE - Real-time formatting as you type!\n\ "🎯 INSERT MODE - Cursor: | (bar)\n\
✏️ Real-time formatting as you type!\n\
\n\ \n\
Current field rules: {}\n\ Current field rules: {}\n\
• Raw input is authoritative (what gets stored)\n\ • Raw input is authoritative (what gets stored)\n\
@@ -701,6 +705,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🧩 Enhanced Canvas Custom Formatter Demo (Feature 4)"); println!("🧩 Enhanced Canvas Custom Formatter Demo (Feature 4)");
println!("✅ validation feature: ENABLED"); println!("✅ validation feature: ENABLED");
println!("✅ gui feature: ENABLED"); println!("✅ gui feature: ENABLED");
println!("✅ cursor-style feature: ENABLED");
println!("🧩 Enhanced features:"); println!("🧩 Enhanced features:");
println!(" • 5 different custom formatters with edge cases"); println!(" • 5 different custom formatters with edge cases");
println!(" • Real-time format preview and validation"); println!(" • Real-time format preview and validation");
@@ -716,7 +721,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let data = MultiFormatterDemoData::new(); let data = MultiFormatterDemoData::new();
let editor = EnhancedDemoEditor::new(data); let mut editor = EnhancedDemoEditor::new(data);
// Initialize with normal mode - library automatically sets block cursor
editor.editor.set_mode(AppMode::ReadOnly);
// Demonstrate that CursorManager is available and working
CursorManager::update_for_mode(AppMode::ReadOnly)?;
let res = run_app(&mut terminal, editor); let res = run_app(&mut terminal, editor);
@@ -724,6 +735,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?; execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?;
terminal.show_cursor()?; terminal.show_cursor()?;
// Library automatically resets cursor on FormEditor::drop()
// But we can also manually reset if needed
CursorManager::reset()?;
if let Err(err) = res { if let Err(err) = res {
println!("{:?}", err); println!("{:?}", err);
} }

View File

@@ -26,14 +26,14 @@
//! - F1: toggle external validation globally //! - F1: toggle external validation globally
//! - F10/Ctrl+C: quit //! - F10/Ctrl+C: quit
//! //!
//! Run: cargo run --example validation_5 --features "gui,validation" //! Run: cargo run --example validation_5 --features "gui,validation,cursor-style"
#![allow(clippy::needless_return)] #![allow(clippy::needless_return)]
#[cfg(not(all(feature = "validation", feature = "gui")))] #[cfg(not(all(feature = "validation", feature = "gui", feature = "cursor-style")))]
compile_error!( compile_error!(
"This example requires the 'validation' and 'gui' features. \ "This example requires the 'validation', 'gui' and 'cursor-style' features. \
Run with: cargo run --example validation_5 --features \"gui,validation\"" Run with: cargo run --example validation_5 --features \"gui,validation,cursor-style\""
); );
use std::io; use std::io;
@@ -59,7 +59,7 @@ use ratatui::{
}; };
use canvas::{ use canvas::{
canvas::{gui::render_canvas_default, modes::AppMode}, canvas::{gui::render_canvas_default, modes::AppMode, CursorManager},
DataProvider, FormEditor, DataProvider, FormEditor,
ValidationConfigBuilder, CustomFormatter, FormattingResult, ValidationConfigBuilder, CustomFormatter, FormattingResult,
validation::ExternalValidationState, validation::ExternalValidationState,
@@ -762,7 +762,7 @@ impl<D: DataProvider> ValidationDemoEditor<D> {
fn enter_edit_mode(&mut self) { fn enter_edit_mode(&mut self) {
self.editor.enter_edit_mode(); self.editor.enter_edit_mode();
let rules = self.field_validation_rules(); let rules = self.field_validation_rules();
self.debug_message = format!("✏️ EDITING {} - {}", self.field_type(), rules); self.debug_message = format!("✏️ INSERT MODE - Cursor: Steady Bar | - {} - {}", self.field_type(), rules);
} }
fn exit_edit_mode(&mut self) { fn exit_edit_mode(&mut self) {
@@ -774,7 +774,7 @@ impl<D: DataProvider> ValidationDemoEditor<D> {
self.validate_field(current_field); self.validate_field(current_field);
} }
self.debug_message = format!("🔒 NORMAL - {}", self.field_type()); self.debug_message = format!("🔒 NORMAL - Cursor: Steady Block █ - {}", self.field_type());
} }
fn next_field(&mut self) { fn next_field(&mut self) {
@@ -915,9 +915,9 @@ fn render_validation_panel(
// Status bar // Status bar
let mode_text = match editor.mode() { let mode_text = match editor.mode() {
AppMode::Edit => "INSERT", AppMode::Edit => "INSERT | (bar cursor)",
AppMode::ReadOnly => "NORMAL", AppMode::ReadOnly => "NORMAL █ (block cursor)",
_ => "OTHER", _ => "NORMAL █ (block cursor)",
}; };
let summary = editor.get_validation_summary(); let summary = editor.get_validation_summary();
@@ -1019,7 +1019,8 @@ fn render_validation_panel(
} else { } else {
let help_text = match editor.mode() { let help_text = match editor.mode() {
AppMode::ReadOnly => { AppMode::ReadOnly => {
"🧪 EXTERNAL VALIDATION DEMO - Multiple validation types with async simulation\n\ "🎯 CURSOR-STYLE: Normal █ | Insert |\n\
🧪 EXTERNAL VALIDATION DEMO - Multiple validation types with async simulation\n\
\n\ \n\
Commands: v=validate current, V=validate all, c=clear current, C=clear all\n\ Commands: v=validate current, V=validate all, c=clear current, C=clear all\n\
e=cycle examples, r=toggle history, h=field help, F1=toggle validation\n\ e=cycle examples, r=toggle history, h=field help, F1=toggle validation\n\
@@ -1028,7 +1029,8 @@ fn render_validation_panel(
Try different values to see validation in action!" Try different values to see validation in action!"
} }
AppMode::Edit => { AppMode::Edit => {
"✏️ EDITING MODE - Type to see validation on field blur\n\ "🎯 INSERT MODE - Cursor: | (bar)\n\
✏️ Type to see validation on field blur\n\
\n\ \n\
Current field validation will trigger when you:\n\ Current field validation will trigger when you:\n\
• Press Esc (exit edit mode)\n\ • Press Esc (exit edit mode)\n\
@@ -1052,6 +1054,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🧪 Enhanced External Validation Demo (Feature 5)"); println!("🧪 Enhanced External Validation Demo (Feature 5)");
println!("✅ validation feature: ENABLED"); println!("✅ validation feature: ENABLED");
println!("✅ gui feature: ENABLED"); println!("✅ gui feature: ENABLED");
println!("✅ cursor-style feature: ENABLED");
println!("🧪 Enhanced features:"); println!("🧪 Enhanced features:");
println!(" • 5 different external validation types with realistic scenarios"); println!(" • 5 different external validation types with realistic scenarios");
println!(" • Validation caching and performance metrics"); println!(" • Validation caching and performance metrics");
@@ -1067,7 +1070,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let data = ValidationDemoData::new(); let data = ValidationDemoData::new();
let editor = ValidationDemoEditor::new(data); let mut editor = ValidationDemoEditor::new(data);
// Initialize with normal mode - library automatically sets block cursor
editor.editor.set_mode(AppMode::ReadOnly);
// Demonstrate that CursorManager is available and working
CursorManager::update_for_mode(AppMode::ReadOnly)?;
let res = run_app(&mut terminal, editor); let res = run_app(&mut terminal, editor);
@@ -1075,6 +1084,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?; execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?;
terminal.show_cursor()?; terminal.show_cursor()?;
// Library automatically resets cursor on FormEditor::drop()
// But we can also manually reset if needed
CursorManager::reset()?;
if let Err(err) = res { if let Err(err) = res {
println!("{:?}", err); println!("{:?}", err);
} }