- Created actions/ module with save, load, delete business logic - Created inputs/keycodes.rs with 30+ keybinding helper functions - Separated business logic from UI/event handling - Added 28 new unit tests and 8 integration tests - Fixed bug: save now requires ctrl+s not just 's' - Reduced ui/mod.rs from 618 to ~290 lines total
5.4 KiB
5.4 KiB
AGENTS.md
Commands
- Build:
cargo build - Run:
cargo run - Test:
cargo test(single test:cargo test <test_name>) - Lint:
cargo clippy - Format:
cargo fmt
Code Style
- Imports: Avoid
enum_glob_use, use explicit imports - Formatting: Run
cargo fmtbefore committing - Clippy: All lints are set to
deny(enum_glob_use, pedantic, nursery, unwrap_used, expect_used). You are not allowed to overwrite this! - Error handling: Never use
unwrap()orexpect(); use proper error handling instead - Naming: Use snake_case for functions/variables, PascalCase for types
Architecture
Module Structure
src/
├── lib.rs # Library root
├── main.rs # CLI entry point
├── models.rs # Domain models (Entry, SortOrder, SortField)
├── state.rs # Application state (AppState, Mode, etc.)
├── db.rs # Database operations (Database struct)
├── error.rs # Error types (Dialog, Toast, etc.)
├── cli.rs # CLI argument parsing
└── ui/
├── mod.rs # Main UI module, event loop
├── overview.rs # List/preview view rendering
├── detail.rs # Detail/edit form rendering
├── dialogs.rs # Dialog, help, toast overlays
├── theme.rs # Color constants and theme
├── components.rs # Shared UI components
├── text_utils.rs # Text processing utilities
├── inputs/ # Input handling (trait-based)
│ ├── mod.rs # InputHandler trait
│ ├── keycodes.rs # Keybinding helper functions
│ ├── list.rs # List mode handler
│ ├── search.rs # Search mode handler
│ ├── detail.rs # Detail mode handler
│ └── dialog.rs # Dialog handler
└── actions/ # Business logic actions
├── mod.rs # Action module
├── save.rs # Save entry action
├── load.rs # Load entries action
└── delete.rs # Delete entry action
Input Handling Pattern
The UI uses a trait-based input handling pattern:
pub trait InputHandler {
fn handle(&mut self, key: KeyEvent, state: &mut AppState, db: &Database) -> Result<()>;
}
Each mode has its own handler:
ListInputHandler- Navigation, create, edit, delete, searchSearchInputHandler- Search query inputDetailInputHandler- Text editing, field navigationDialogInputHandler- Yes/no confirmations
Actions Module
Business logic is extracted to the actions/ module:
save::execute()- Save entry (create or update)load::execute()- Load entries from databasedelete::execute()- Delete entry by IDexecute_dialog_action()- Handle dialog confirmations
Shared Utilities
text_utils::extract_tags_and_mentions()- Parses#tagsand@mentionsfrom textcomponents::draw_timestamps()- Renders created/modified timestampscomponents::draw_subject_field()- Renders subject textareacomponents::draw_message_field()- Renders message textarea
State Management
AppState in state.rs contains:
- Mode: List, Search, or Detail
- Entries: Vector of all entries
- Selection: selected_index, search_matches, search_match_index
- Sorting: sort_field, sort_order
- Search: search_query, search_active
- Detail editing: detail_mode, detail_field, textareas, original_entry
- UI state: dialog, toast, show_help, areas for mouse detection
Rendering
The UI is rendered using ratatui:
overview::draw()- List + preview split viewdetail::draw()- Edit/create formdialogs::draw_dialog()- Confirmation dialogsdialogs::draw_help()- Help overlaydialogs::draw_toast()- Notification toasts
Database
Database in db.rs provides:
insert()- Create new entryupdate()- Modify existing entrydelete()- Remove entry by IDget_all()- Query entries with sorting/filteringexport_json()/export_csv()- Export dataimport_json()/import_csv()- Import data
Refactoring History
Phase 1: Shared Utilities (COMPLETED)
- Created
text_utils.rswithextract_tags_and_mentions() - Created
components.rswith shared rendering functions - Eliminated ~180 lines of duplicated code
Phase 2: Input Handlers (COMPLETED)
- Created
inputs/module with trait-based handlers - Extracted List, Search, Detail, Dialog handlers
- Added 17 unit tests for input handling
- Reduced
ui/mod.rsfrom 618 to 364 lines (-41%)
Phase 3: Actions Module (COMPLETED)
- Created
actions/module with save, load, delete actions - Separated business logic from UI/event handling
- Added 8 integration tests for UI workflows
- Reduced
ui/mod.rsfrom 392 to ~290 lines (-26%)
Phase 4: Keybinding Constants (COMPLETED)
- Created
inputs/keycodes.rswith helper functions for key matching - Added 30+ keycode helper functions (esc, ctrl_c, enter, tab, etc.)
- Updated all input handlers to use named functions instead of raw patterns
- All 78 tests pass, clean clippy output
Future Improvements
- Create
NavigationStatestruct to separate navigation from UI state - Add mouse click tests
- Create
Themestruct for extensibility - Consider command pattern for undo/redo functionality