diff options
| author | rottedfm <rottedfm@proton.me> | 2026-08-19 11:24:55 -0400 |
|---|---|---|
| committer | rottedfm <rottedfm@proton.me> | 2026-08-19 11:24:55 -0400 |
| commit | 8e16347b0eb329e84892af8ece36886324c95f62 (patch) | |
| tree | be1267972b5de2f1ae592577dfabce67f1fe6e87 /src/components.rs | |
| parent | c6ae4660d1cc2414b22c492c5e819d009c8187c2 (diff) | |
| parent | ea0bd36167b684c0accdb5ce2b2e21b8d84aeb25 (diff) | |
Establishes the first working baseline: moji <file> opens a file into a
ropey rope and edits it with Helix selection-first modal editing, under a
DO-178C DAL-C requirements and traceability process.
Prior to this, main tracked four files and src/main.rs was still
println!("Hello, world!") — there was no buildable state to build on.
Verified on a fresh clone of the branch with no untracked files:
cargo build; clippy --all-targets -D warnings clean; 294 tests passing;
scripts/check-trace.sh reports 98/98 requirements traced in both
directions.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'src/components.rs')
| -rw-r--r-- | src/components.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/components.rs b/src/components.rs new file mode 100644 index 0000000..1771a17 --- /dev/null +++ b/src/components.rs @@ -0,0 +1,125 @@ +use crossterm::event::{KeyEvent, MouseEvent}; +use ratatui::{ + Frame, + layout::{Rect, Size}, +}; +use tokio::sync::mpsc::UnboundedSender; + +use crate::{action::Action, config::Config, tui::Event}; + +// MJB-LLR-204, MJB-HLR-019: the buffer is the only widget. The template's +// `fps` and `home` modules were deleted, not merely unregistered. +pub mod buffer; + +/// `Component` is a trait that represents a visual and interactive element of the user interface. +/// +/// Implementors of this trait can be registered with the main application loop and will be able to +/// receive events, update state, and be rendered on the screen. +pub trait Component { + /// Register an action handler that can send actions for processing if necessary. + /// + /// # Arguments + /// + /// * `tx` - An unbounded sender that can send actions. + /// + /// # Returns + /// + /// * [`color_eyre::Result<()>`] - An Ok result or an error. + fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> color_eyre::Result<()> { + let _ = tx; // to appease clippy + Ok(()) + } + /// Register a configuration handler that provides configuration settings if necessary. + /// + /// # Arguments + /// + /// * `config` - Configuration settings. + /// + /// # Returns + /// + /// * [`color_eyre::Result<()>`] - An Ok result or an error. + fn register_config_handler(&mut self, config: Config) -> color_eyre::Result<()> { + let _ = config; // to appease clippy + Ok(()) + } + /// Initialize the component with a specified area if necessary. + /// + /// # Arguments + /// + /// * `area` - Rectangular area to initialize the component within. + /// + /// # Returns + /// + /// * [`color_eyre::Result<()>`] - An Ok result or an error. + fn init(&mut self, area: Size) -> color_eyre::Result<()> { + let _ = area; // to appease clippy + Ok(()) + } + /// Handle incoming events and produce actions if necessary. + /// + /// # Arguments + /// + /// * `event` - An optional event to be processed. + /// + /// # Returns + /// + /// * [`color_eyre::Result<Option<Action>>`] - An action to be processed or none. + fn handle_events(&mut self, event: Option<Event>) -> color_eyre::Result<Option<Action>> { + let action = match event { + Some(Event::Key(key_event)) => self.handle_key_event(key_event)?, + Some(Event::Mouse(mouse_event)) => self.handle_mouse_event(mouse_event)?, + _ => None, + }; + Ok(action) + } + /// Handle key events and produce actions if necessary. + /// + /// # Arguments + /// + /// * `key` - A key event to be processed. + /// + /// # Returns + /// + /// * [`color_eyre::Result<Option<Action>>`] - An action to be processed or none. + fn handle_key_event(&mut self, key: KeyEvent) -> color_eyre::Result<Option<Action>> { + let _ = key; // to appease clippy + Ok(None) + } + /// Handle mouse events and produce actions if necessary. + /// + /// # Arguments + /// + /// * `mouse` - A mouse event to be processed. + /// + /// # Returns + /// + /// * [`color_eyre::Result<Option<Action>>`] - An action to be processed or none. + fn handle_mouse_event(&mut self, mouse: MouseEvent) -> color_eyre::Result<Option<Action>> { + let _ = mouse; // to appease clippy + Ok(None) + } + /// Update the state of the component based on a received action. (REQUIRED) + /// + /// # Arguments + /// + /// * `action` - An action that may modify the state of the component. + /// + /// # Returns + /// + /// * [`color_eyre::Result<Option<Action>>`] - An action to be processed or none. + fn update(&mut self, action: Action) -> color_eyre::Result<Option<Action>> { + let _ = action; // to appease clippy + Ok(None) + } + /// Render the component on the screen. (REQUIRED) + /// + /// # Arguments + /// + /// * `f` - A frame used for rendering. + /// * `area` - The area in which the component should be drawn. + /// + /// # Returns + /// + /// * [`color_eyre::Result<()>`] - An Ok result or an error. + fn draw(&mut self, frame: &mut Frame, area: Rect) -> color_eyre::Result<()>; +} |
