prod comments in the codebase
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// src/canvas/actions/mod.rs
|
||||
//! Canvas action definitions and movement utilities
|
||||
|
||||
pub mod types;
|
||||
pub mod movement;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// src/canvas/actions/movement/char.rs
|
||||
//! Character-level cursor movement functions
|
||||
|
||||
/// Calculate new position when moving left
|
||||
pub fn move_left(current_pos: usize) -> usize {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// src/canvas/actions/movement/line.rs
|
||||
//! Line-level cursor movement and positioning
|
||||
|
||||
/// Calculate cursor position for line start
|
||||
pub fn line_start_position() -> usize {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// src/canvas/actions/movement/mod.rs
|
||||
//! Movement utilities for character, word, and line navigation
|
||||
|
||||
pub mod word;
|
||||
pub mod line;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// src/canvas/actions/movement/word.rs
|
||||
// Replace the entire file with this corrected version:
|
||||
//! Word-based cursor movement with vim-like semantics
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum CharType {
|
||||
|
||||
@@ -1,79 +1,121 @@
|
||||
// src/canvas/actions/types.rs
|
||||
//! Core action types and result handling for canvas operations.
|
||||
|
||||
/// All available canvas actions
|
||||
/// All available canvas actions.
|
||||
///
|
||||
/// This enum lists high-level actions that can be performed on the canvas.
|
||||
/// Consumers can match on variants to implement custom handling or map input
|
||||
/// events to these canonical actions.
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CanvasAction {
|
||||
// Movement actions
|
||||
/// Move the cursor left by one character (or logical unit).
|
||||
MoveLeft,
|
||||
/// Move the cursor right by one character (or logical unit).
|
||||
MoveRight,
|
||||
/// Move the cursor up a visual line/field.
|
||||
MoveUp,
|
||||
/// Move the cursor down a visual line/field.
|
||||
MoveDown,
|
||||
|
||||
// Word movement
|
||||
/// Move to the start of the next word.
|
||||
MoveWordNext,
|
||||
/// Move to the start of the previous word.
|
||||
MoveWordPrev,
|
||||
/// Move to the end of the current/next word.
|
||||
MoveWordEnd,
|
||||
/// Move to the previous word end (vim `ge`).
|
||||
MoveWordEndPrev,
|
||||
|
||||
// Line movement
|
||||
/// Move to the start of the current line.
|
||||
MoveLineStart,
|
||||
/// Move to the end of the current line.
|
||||
MoveLineEnd,
|
||||
|
||||
// Field movement
|
||||
/// Move to the next field.
|
||||
NextField,
|
||||
/// Move to the previous field.
|
||||
PrevField,
|
||||
/// Move to the first field.
|
||||
MoveFirstLine,
|
||||
/// Move to the last field.
|
||||
MoveLastLine,
|
||||
|
||||
// Editing actions
|
||||
/// Insert a character at the cursor.
|
||||
InsertChar(char),
|
||||
/// Delete character before the cursor.
|
||||
DeleteBackward,
|
||||
/// Delete character under/after the cursor.
|
||||
DeleteForward,
|
||||
|
||||
// Suggestions actions
|
||||
TriggerSuggestions,
|
||||
SuggestionUp,
|
||||
SuggestionDown,
|
||||
SelectSuggestion,
|
||||
ExitSuggestions,
|
||||
/// Trigger suggestions dropdown (e.g. Tab).
|
||||
TriggerSuggestions,
|
||||
/// Move selection up in suggestions dropdown.
|
||||
SuggestionUp,
|
||||
/// Move selection down in suggestions dropdown.
|
||||
SuggestionDown,
|
||||
/// Accept the selected suggestion.
|
||||
SelectSuggestion,
|
||||
/// Exit suggestions UI.
|
||||
ExitSuggestions,
|
||||
|
||||
// Custom actions
|
||||
/// Custom named action for application-specific behavior.
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
/// Result type for canvas actions
|
||||
/// Result type for canvas actions.
|
||||
///
|
||||
/// Action handlers return an ActionResult to indicate success, user-facing
|
||||
/// messages, or errors. The enum is non-exhaustive to allow extension.
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ActionResult {
|
||||
/// Action completed successfully.
|
||||
Success,
|
||||
/// Action completed with a user-facing message.
|
||||
Message(String),
|
||||
/// Action was handled by the application with an associated message.
|
||||
HandledByApp(String),
|
||||
/// Action was handled by a feature with an associated message.
|
||||
HandledByFeature(String), // Keep for compatibility
|
||||
/// An error occurred while handling the action.
|
||||
Error(String),
|
||||
}
|
||||
|
||||
impl ActionResult {
|
||||
/// Convenience constructor for Success.
|
||||
pub fn success() -> Self {
|
||||
Self::Success
|
||||
}
|
||||
|
||||
/// Convenience constructor for Message.
|
||||
pub fn success_with_message(msg: &str) -> Self {
|
||||
Self::Message(msg.to_string())
|
||||
}
|
||||
|
||||
/// Convenience constructor for HandledByApp.
|
||||
pub fn handled_by_app(msg: &str) -> Self {
|
||||
Self::HandledByApp(msg.to_string())
|
||||
}
|
||||
|
||||
/// Convenience constructor for Error.
|
||||
pub fn error(msg: &str) -> Self {
|
||||
Self::Error(msg.to_string())
|
||||
}
|
||||
|
||||
/// Returns true for any variant representing a success-like outcome.
|
||||
pub fn is_success(&self) -> bool {
|
||||
matches!(self, Self::Success | Self::Message(_) | Self::HandledByApp(_) | Self::HandledByFeature(_))
|
||||
}
|
||||
|
||||
/// Extract a message from the result when present.
|
||||
pub fn message(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Message(msg) | Self::HandledByApp(msg) | Self::HandledByFeature(msg) | Self::Error(msg) => Some(msg),
|
||||
@@ -83,7 +125,7 @@ impl ActionResult {
|
||||
}
|
||||
|
||||
impl CanvasAction {
|
||||
/// Get a human-readable description of this action
|
||||
/// Get a human-readable description of this action.
|
||||
pub fn description(&self) -> &'static str {
|
||||
match self {
|
||||
Self::MoveLeft => "move left",
|
||||
@@ -112,7 +154,7 @@ impl CanvasAction {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all movement-related actions
|
||||
/// Get all movement-related actions.
|
||||
pub fn movement_actions() -> Vec<CanvasAction> {
|
||||
vec![
|
||||
Self::MoveLeft,
|
||||
@@ -132,7 +174,7 @@ impl CanvasAction {
|
||||
]
|
||||
}
|
||||
|
||||
/// Get all editing-related actions
|
||||
/// Get all editing-related actions.
|
||||
pub fn editing_actions() -> Vec<CanvasAction> {
|
||||
vec![
|
||||
Self::InsertChar(' '), // Example char
|
||||
@@ -141,7 +183,7 @@ impl CanvasAction {
|
||||
]
|
||||
}
|
||||
|
||||
/// Get all suggestions-related actions
|
||||
/// Get all suggestions-related actions.
|
||||
pub fn suggestions_actions() -> Vec<CanvasAction> {
|
||||
vec![
|
||||
Self::TriggerSuggestions,
|
||||
@@ -152,7 +194,7 @@ impl CanvasAction {
|
||||
]
|
||||
}
|
||||
|
||||
/// Check if this action modifies text content
|
||||
/// Check if this action modifies text content.
|
||||
pub fn is_editing_action(&self) -> bool {
|
||||
matches!(self,
|
||||
Self::InsertChar(_) |
|
||||
@@ -161,7 +203,7 @@ impl CanvasAction {
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if this action moves the cursor
|
||||
/// Check if this action moves the cursor.
|
||||
pub fn is_movement_action(&self) -> bool {
|
||||
matches!(self,
|
||||
Self::MoveLeft | Self::MoveRight | Self::MoveUp | Self::MoveDown |
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
// src/canvas/cursor.rs
|
||||
//! Cursor style management for different canvas modes
|
||||
//!
|
||||
//! Provides helpers to update and reset terminal cursor style when the
|
||||
//! `cursor-style` feature is enabled. When the feature is disabled the
|
||||
//! functions are no-ops.
|
||||
|
||||
#[cfg(feature = "cursor-style")]
|
||||
use crossterm::{cursor::SetCursorStyle, execute};
|
||||
@@ -12,7 +16,10 @@ use crate::canvas::modes::AppMode;
|
||||
pub struct CursorManager;
|
||||
|
||||
impl CursorManager {
|
||||
/// Update cursor style based on current mode
|
||||
/// Update cursor style based on current mode.
|
||||
///
|
||||
/// When the `textmode-normal` feature is enabled a fixed style is applied.
|
||||
/// Otherwise, the cursor style is mapped to the provided AppMode.
|
||||
#[cfg(feature = "cursor-style")]
|
||||
pub fn update_for_mode(mode: AppMode) -> io::Result<()> {
|
||||
// NORMALMODE: force underscore for every mode
|
||||
@@ -37,18 +44,19 @@ impl CursorManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op when cursor-style feature is disabled
|
||||
/// No-op when cursor-style feature is disabled.
|
||||
#[cfg(not(feature = "cursor-style"))]
|
||||
pub fn update_for_mode(_mode: AppMode) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset cursor to default on cleanup
|
||||
/// Reset cursor to default on cleanup.
|
||||
#[cfg(feature = "cursor-style")]
|
||||
pub fn reset() -> io::Result<()> {
|
||||
execute!(io::stdout(), SetCursorStyle::DefaultUserShape)
|
||||
}
|
||||
|
||||
/// Reset is a no-op when the cursor-style feature is disabled.
|
||||
#[cfg(not(feature = "cursor-style"))]
|
||||
pub fn reset() -> io::Result<()> {
|
||||
Ok(())
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
// src/canvas/gui.rs
|
||||
//! Canvas GUI updated to work with FormEditor
|
||||
//!
|
||||
//! This module provides rendering helpers for the canvas UI when the `gui`
|
||||
//! feature is enabled. It exposes high-level functions to render the canvas
|
||||
//! and convenience types for display options.
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
use ratatui::{
|
||||
@@ -22,14 +26,20 @@ use std::cmp::{max, min};
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// How to handle overflow when rendering a field's content.
|
||||
pub enum OverflowMode {
|
||||
Indicator(char), // default '$'
|
||||
/// Show an indicator character at the left/right when text is truncated.
|
||||
/// Common default is '$'.
|
||||
Indicator(char),
|
||||
/// Wrap content into multiple visual lines.
|
||||
Wrap,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// Display options controlling canvas rendering behavior.
|
||||
pub struct CanvasDisplayOptions {
|
||||
/// How to handle horizontal overflow for fields.
|
||||
pub overflow: OverflowMode,
|
||||
}
|
||||
|
||||
@@ -191,6 +201,9 @@ fn render_active_line_with_indicator<T: CanvasTheme>(
|
||||
}
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
/// Render the canvas into the provided frame using default display options.
|
||||
///
|
||||
/// Returns the rectangle of the active input field if present.
|
||||
pub fn render_canvas<T: CanvasTheme, D: DataProvider>(
|
||||
f: &mut Frame,
|
||||
area: Rect,
|
||||
@@ -202,6 +215,10 @@ pub fn render_canvas<T: CanvasTheme, D: DataProvider>(
|
||||
}
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
/// Render the canvas into the provided frame with explicit display options.
|
||||
///
|
||||
/// This is the more configurable entrypoint for rendering and is useful for
|
||||
/// tests or when callers need to override overflow handling.
|
||||
pub fn render_canvas_with_options<T: CanvasTheme, D: DataProvider>(
|
||||
f: &mut Frame,
|
||||
area: Rect,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
// src/canvas/mod.rs
|
||||
//! Top-level canvas module.
|
||||
//!
|
||||
//! Re-exports commonly used canvas types and modules so that downstream
|
||||
//! consumers can import them from `crate::canvas`.
|
||||
|
||||
pub mod actions;
|
||||
pub mod state;
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
// src/state/app/highlight.rs
|
||||
// canvas/src/modes/highlight.rs
|
||||
// src/canvas/modes/highlight.rs
|
||||
//! Highlight state definitions for canvas visual/selection modes.
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default)]
|
||||
/// Represents the current highlight/visual selection state.
|
||||
///
|
||||
/// This enum is used by the GUI and selection logic to track whether a visual
|
||||
/// selection is active and its anchor position.
|
||||
pub enum HighlightState {
|
||||
/// No highlighting active.
|
||||
#[default]
|
||||
Off,
|
||||
/// Characterwise selection with an anchor (field_index, char_position).
|
||||
Characterwise { anchor: (usize, usize) }, // (field_index, char_position)
|
||||
/// Linewise selection anchored at a field index.
|
||||
Linewise { anchor_line: usize }, // field_index
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,61 @@
|
||||
// src/modes/handlers/mode_manager.rs
|
||||
// canvas/src/modes/manager.rs
|
||||
//! Mode manager utilities and the AppMode enum.
|
||||
//!
|
||||
//! This module defines the available canvas modes and provides helper
|
||||
//! functions to validate mode transitions and perform required side-effects
|
||||
//! such as updating cursor style when enabled.
|
||||
|
||||
#[cfg(feature = "cursor-style")]
|
||||
use crate::canvas::CursorManager;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
/// Top-level application modes used by the canvas UI.
|
||||
///
|
||||
/// These modes control input handling, cursor behavior, and how the UI should
|
||||
/// respond to user actions.
|
||||
pub enum AppMode {
|
||||
General, // For intro and admin screens
|
||||
ReadOnly, // Canvas read-only mode
|
||||
Edit, // Canvas edit mode
|
||||
Highlight, // Canvas highlight/visual mode
|
||||
Command, // Command mode overlay
|
||||
/// For intro and admin screens
|
||||
General,
|
||||
/// Canvas read-only mode (navigation)
|
||||
ReadOnly,
|
||||
/// Canvas edit mode (insertion/modification)
|
||||
Edit,
|
||||
/// Canvas highlight/visual mode (selection)
|
||||
Highlight,
|
||||
/// Command mode overlay (for commands)
|
||||
Command,
|
||||
}
|
||||
|
||||
pub struct ModeManager;
|
||||
|
||||
impl ModeManager {
|
||||
// Mode transition rules
|
||||
|
||||
/// Return true if the system can enter Command mode from the given current mode.
|
||||
pub fn can_enter_command_mode(current_mode: AppMode) -> bool {
|
||||
!matches!(current_mode, AppMode::Edit)
|
||||
}
|
||||
|
||||
/// Return true if the system can enter Edit mode from the given current mode.
|
||||
pub fn can_enter_edit_mode(current_mode: AppMode) -> bool {
|
||||
matches!(current_mode, AppMode::ReadOnly)
|
||||
}
|
||||
|
||||
/// Return true if the system can enter ReadOnly mode from the given current mode.
|
||||
pub fn can_enter_read_only_mode(current_mode: AppMode) -> bool {
|
||||
matches!(current_mode, AppMode::Edit | AppMode::Command | AppMode::Highlight)
|
||||
}
|
||||
|
||||
/// Return true if the system can enter Highlight mode from the given current mode.
|
||||
pub fn can_enter_highlight_mode(current_mode: AppMode) -> bool {
|
||||
matches!(current_mode, AppMode::ReadOnly)
|
||||
}
|
||||
|
||||
|
||||
/// Transition to new mode with automatic cursor update (when cursor-style feature enabled)
|
||||
/// Transition to new mode with automatic cursor update (when cursor-style feature enabled).
|
||||
///
|
||||
/// Returns the resulting mode or an I/O error if cursor style update fails.
|
||||
pub fn transition_to_mode(current_mode: AppMode, new_mode: AppMode) -> std::io::Result<AppMode> {
|
||||
#[cfg(feature = "textmode-normal")]
|
||||
{
|
||||
@@ -54,7 +75,10 @@ impl ModeManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enter highlight mode with cursor styling
|
||||
/// Enter highlight mode with cursor styling.
|
||||
///
|
||||
/// Returns Ok(true) if the transition succeeded (and cursor style was updated
|
||||
/// when enabled), otherwise Ok(false) if the transition is not allowed.
|
||||
pub fn enter_highlight_mode_with_cursor(current_mode: AppMode) -> std::io::Result<bool> {
|
||||
if Self::can_enter_highlight_mode(current_mode) {
|
||||
#[cfg(feature = "cursor-style")]
|
||||
@@ -67,7 +91,10 @@ impl ModeManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Exit highlight mode with cursor styling
|
||||
/// Exit highlight mode with cursor styling and return the next mode.
|
||||
///
|
||||
/// This helper returns the mode to switch to (ReadOnly) and updates cursor
|
||||
/// style if the feature is enabled.
|
||||
pub fn exit_highlight_mode_with_cursor() -> std::io::Result<AppMode> {
|
||||
let new_mode = AppMode::ReadOnly;
|
||||
#[cfg(feature = "cursor-style")]
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
// src/canvas/state.rs
|
||||
//! Library-owned UI state - user never directly modifies this
|
||||
//!
|
||||
//! This module exposes the EditorState type (and related selection and
|
||||
//! suggestions types) which represent the internal UI state maintained by the
|
||||
//! canvas library. These types are intended for read-only access by callers
|
||||
//! and are mutated only through the library's APIs.
|
||||
|
||||
use crate::canvas::modes::AppMode;
|
||||
|
||||
/// Library-owned UI state - user never directly modifies this
|
||||
#[derive(Debug, Clone)]
|
||||
/// Internal editor UI state managed by the canvas library.
|
||||
///
|
||||
/// The fields are `pub(crate)` because they should only be modified by the
|
||||
/// library's internal action handlers. Consumers can use the provided getter
|
||||
/// methods to observe the state.
|
||||
pub struct EditorState {
|
||||
// Navigation state
|
||||
pub(crate) current_field: usize,
|
||||
@@ -32,6 +42,7 @@ pub struct EditorState {
|
||||
|
||||
#[cfg(feature = "suggestions")]
|
||||
#[derive(Debug, Clone)]
|
||||
/// Internal suggestions UI state used to manage the suggestions dropdown.
|
||||
pub struct SuggestionsUIState {
|
||||
pub(crate) is_active: bool,
|
||||
pub(crate) is_loading: bool,
|
||||
@@ -42,13 +53,19 @@ pub struct SuggestionsUIState {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// SelectionState represents the current selection/visual mode state used by
|
||||
/// the canvas (for example, Vim-like visual modes).
|
||||
pub enum SelectionState {
|
||||
/// No selection is active.
|
||||
None,
|
||||
/// Characterwise selection: (field_index, char_position)
|
||||
Characterwise { anchor: (usize, usize) },
|
||||
/// Linewise selection anchored at a field (field index).
|
||||
Linewise { anchor_field: usize },
|
||||
}
|
||||
|
||||
impl EditorState {
|
||||
/// Create a new EditorState with default initial values.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
current_field: 0,
|
||||
@@ -139,6 +156,10 @@ impl EditorState {
|
||||
// INTERNAL MUTATIONS: Only library modifies these
|
||||
// ===================================================================
|
||||
|
||||
/// Move internal pointer to another field index.
|
||||
///
|
||||
/// This method is intended for internal library use to change the current
|
||||
/// field and reset the cursor to a safe value.
|
||||
pub(crate) fn move_to_field(&mut self, field_index: usize, field_count: usize) {
|
||||
if field_index < field_count {
|
||||
self.current_field = field_index;
|
||||
@@ -147,6 +168,11 @@ impl EditorState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the cursor position with appropriate clamping depending on mode.
|
||||
///
|
||||
/// If `for_edit_mode` is true the cursor may be positioned at the end of
|
||||
/// the text (allowing insertion); otherwise it will be kept within the
|
||||
/// bounds of the existing text for read-only/highlight modes.
|
||||
pub(crate) fn set_cursor(
|
||||
&mut self,
|
||||
position: usize,
|
||||
|
||||
Reference in New Issue
Block a user