prod comments in the codebase

This commit is contained in:
Priec
2025-08-18 21:00:14 +02:00
parent 885a48bdd8
commit 465db82bd9
12 changed files with 163 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
// src/canvas/actions/mod.rs
//! Canvas action definitions and movement utilities
pub mod types;
pub mod movement;

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -1,4 +1,5 @@
// src/canvas/actions/movement/mod.rs
//! Movement utilities for character, word, and line navigation
pub mod word;
pub mod line;

View File

@@ -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 {

View File

@@ -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 |

View File

@@ -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(())

View File

@@ -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,

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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")]

View File

@@ -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,