Skip to main content

axonml_tui/
lib.rs

1//! Axonml TUI - Terminal User Interface for ML Framework
2//!
3//! A comprehensive terminal-based user interface for the Axonml ML framework,
4//! providing visualization of models, datasets, training progress, and more.
5//!
6//! # Features
7//! - Model architecture visualization
8//! - Dataset structure and statistics
9//! - Real-time training progress monitoring
10//! - Loss and accuracy graphs
11//! - File browser for models and datasets
12//!
13//! # Example
14//! ```no_run
15//! use axonml_tui::run;
16//!
17//! fn main() -> std::io::Result<()> {
18//!     run(None, None)
19//! }
20//! ```
21//!
22//! @version 0.1.0
23//! @author AutomataNexus Development Team
24
25#![warn(missing_docs)]
26#![warn(clippy::all)]
27#![warn(clippy::pedantic)]
28// TUI-specific allowances
29#![allow(clippy::cast_possible_truncation)]
30#![allow(clippy::cast_sign_loss)]
31#![allow(clippy::cast_precision_loss)]
32#![allow(clippy::missing_errors_doc)]
33#![allow(clippy::missing_panics_doc)]
34#![allow(clippy::must_use_candidate)]
35#![allow(clippy::module_name_repetitions)]
36#![allow(clippy::similar_names)]
37#![allow(clippy::too_many_lines)]
38#![allow(clippy::doc_markdown)]
39#![allow(clippy::uninlined_format_args)]
40#![allow(clippy::needless_pass_by_value)]
41#![allow(clippy::unused_self)]
42#![allow(clippy::match_same_arms)]
43#![allow(clippy::single_match_else)]
44#![allow(clippy::items_after_statements)]
45#![allow(clippy::manual_div_ceil)]
46#![allow(clippy::struct_field_names)]
47#![allow(clippy::option_map_or_none)]
48#![allow(clippy::map_unwrap_or)]
49#![allow(clippy::unnecessary_wraps)]
50#![allow(clippy::trivially_copy_pass_by_ref)]
51#![allow(clippy::redundant_else)]
52#![allow(clippy::needless_raw_string_hashes)]
53#![allow(clippy::needless_bool)]
54#![allow(clippy::bool_comparison)]
55#![allow(clippy::should_implement_trait)]
56#![allow(clippy::nonminimal_bool)]
57#![allow(clippy::return_self_not_must_use)]
58
59pub mod app;
60pub mod event;
61pub mod theme;
62pub mod ui;
63pub mod views;
64
65pub use app::{App, Tab};
66pub use theme::AxonmlTheme;
67pub use views::{DataView, FilesView, GraphsView, HelpView, ModelView, TrainingView};
68
69use std::io::{self, stdout};
70use std::path::PathBuf;
71use std::time::Duration;
72
73use crossterm::{
74    event::Event,
75    execute,
76    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
77};
78use ratatui::prelude::*;
79
80// =============================================================================
81// Main Entry Point
82// =============================================================================
83
84/// Run the Axonml TUI application
85///
86/// # Arguments
87/// * `model_path` - Optional path to a model file to load on startup
88/// * `data_path` - Optional path to a dataset directory to load on startup
89///
90/// # Errors
91/// Returns an error if terminal initialization fails
92pub fn run(model_path: Option<PathBuf>, data_path: Option<PathBuf>) -> io::Result<()> {
93    // Setup terminal
94    enable_raw_mode()?;
95    let mut stdout = stdout();
96    execute!(stdout, EnterAlternateScreen)?;
97    let backend = CrosstermBackend::new(stdout);
98    let mut terminal = Terminal::new(backend)?;
99
100    // Create application state
101    let mut app = App::new();
102
103    // Load model if provided
104    if let Some(path) = model_path {
105        app.load_model(path);
106    }
107
108    // Load dataset if provided
109    if let Some(path) = data_path {
110        app.load_dataset(path);
111    }
112
113    // Main loop
114    let result = run_app(&mut terminal, &mut app);
115
116    // Restore terminal
117    disable_raw_mode()?;
118    execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
119    terminal.show_cursor()?;
120
121    result
122}
123
124/// Main application loop
125fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<()> {
126    loop {
127        // Render
128        terminal.draw(|frame| {
129            ui::render(app, frame);
130        })?;
131
132        // Handle events
133        if event::poll_event(Duration::from_millis(100))? {
134            if let Event::Key(key) = event::read_event()? {
135                event::handle_key_event(app, key);
136            }
137        }
138
139        // Check if we should quit
140        if app.should_quit {
141            return Ok(());
142        }
143
144        // Update training view if active (for real-time updates)
145        if app.active_tab == Tab::Training {
146            app.training_view.tick();
147        }
148    }
149}
150
151// =============================================================================
152// Tests
153// =============================================================================
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158
159    #[test]
160    fn test_app_creation() {
161        let app = App::new();
162        assert_eq!(app.active_tab, Tab::Model);
163        assert!(!app.should_quit);
164    }
165}