noctua/core/examples/cli.rs
mow c85f35310e chore: inital commit
Split project into a Cargo workspace with two crates:

- core/ (noctua_core): UI-independent document library
- ui/ (noctua_ui): COSMIC application scaffold (empty)

justfile for workspace (run, run-cli, check, test, build)
2026-03-07 20:29:18 +01:00

147 lines
4.9 KiB
Rust

// SPDX-License-Identifier: GPL-3.0-or-later
// examples/cli.rs
//
// CLI test harness for the noctua_core document foundation.
use clap::{ArgGroup, Parser};
use noctua_core::document::manager::{DocumentCommand, DocumentManager, DocumentState};
use noctua_core::document::session::SessionKind;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(
name = "noctua",
about = "A document viewer for the COSMIC desktop",
group(
ArgGroup::new("source")
.required(true)
.args(["open_document", "open_directory", "open_session"])
)
)]
struct Cli {
/// Open a document (Raster, Vector, Portable)
#[arg(long, value_name = "PATH")]
open_document: Option<PathBuf>,
/// Open a directory
#[arg(long, value_name = "PATH")]
open_directory: Option<PathBuf>,
/// Open a session file (.ron)
#[arg(long, value_name = "PATH")]
open_session: Option<PathBuf>,
}
fn main() {
env_logger::init();
let cli = Cli::parse();
let mut manager = DocumentManager::new();
if let Some(path) = cli.open_session {
manager.handle(DocumentCommand::OpenSession(path));
} else if let Some(path) = cli.open_document {
let dir = path
.parent()
.map(|p| p.to_path_buf())
.unwrap_or_else(|| PathBuf::from("."));
let session_name = dir
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("Browse")
.to_string();
if manager.session(&session_name).is_none() {
manager.handle(DocumentCommand::CreateSession {
name: session_name.clone(),
kind: SessionKind::DirectoryBrowser,
path: Some(dir.clone()),
});
manager.handle(DocumentCommand::ScanDirectory {
session: session_name.clone(),
dir,
});
}
manager.handle(DocumentCommand::AddFileToSession {
session: session_name,
path,
});
} else if let Some(path) = cli.open_directory {
let session_name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("Browse")
.to_string();
if manager.session(&session_name).is_none() {
manager.handle(DocumentCommand::CreateSession {
name: session_name.clone(),
kind: SessionKind::DirectoryBrowser,
path: Some(path.clone()),
});
manager.handle(DocumentCommand::ScanDirectory {
session: session_name.clone(),
dir: path,
});
}
manager.handle(DocumentCommand::SetActive(session_name));
}
match &manager.state {
DocumentState::Empty => println!("UI: No document loaded."),
DocumentState::Loading => println!("UI: Loading..."),
DocumentState::Error(err) => eprintln!("UI: Error -> {err}"),
DocumentState::Loaded(_) => {
println!("UI: Document loaded.");
if let Some(name) = manager.active_session_name.clone() {
if let Some(session) = manager.session(&name) {
println!(
"UI: Session '{}' ({:?}) has {} items, current index: {:?}",
session.name,
session.kind,
session.items.len(),
session.current_index
);
match session.kind {
SessionKind::DirectoryBrowser => {
println!("UI: Display as directory browser (thumbnails in left panel)");
}
SessionKind::DocumentCollection => {
println!("UI: Display as document collection (pages)");
}
}
}
println!("\nUI: Test navigation...");
manager.handle(DocumentCommand::NavigateNext);
if let Some(session) = manager.session(&name) {
println!(
"UI: After NavigateNext -> index {:?}",
session.current_index
);
}
manager.handle(DocumentCommand::NavigatePrevious);
if let Some(session) = manager.session(&name) {
println!(
"UI: After NavigatePrevious -> index {:?}",
session.current_index
);
}
manager.handle(DocumentCommand::SelectItem(0));
if let Some(session) = manager.session(&name) {
println!(
"UI: After SelectItem(0) -> index {:?}",
session.current_index
);
}
}
}
}
}