refactor(examples/cli): update to new SessionCommand API

This commit is contained in:
mow 2026-03-09 21:06:51 +01:00
parent 7fa218e68c
commit 767315a65e

View file

@ -6,10 +6,10 @@
use clap::{ArgGroup, Parser}; use clap::{ArgGroup, Parser};
use noctua_core::document::manager::{DocumentManager, DocumentState}; use noctua_core::document::manager::{DocumentManager, DocumentState};
use noctua_core::document::session::command::SessionCommand; use noctua_core::document::session::command::SessionCommand;
use noctua_core::document::session::data::CollectionKind; use noctua_core::document::session::data::{CollectionKind, SessionData};
use std::path::PathBuf; use std::path::PathBuf;
// ── ANSI helpers ── // ANSI helpers
const RESET: &str = "\x1b[0m"; const RESET: &str = "\x1b[0m";
const BOLD: &str = "\x1b[1m"; const BOLD: &str = "\x1b[1m";
@ -40,36 +40,32 @@ fn info(text: &str) {
println!(" {YELLOW}i{RESET} {text}"); println!(" {YELLOW}i{RESET} {text}");
} }
fn print_session(manager: &DocumentManager, session_name: &str) { fn print_session(session: &SessionData, active_doc_index: Option<usize>) {
if let Some(session) = manager.session(session_name) { let kind_label = match session.kind {
let kind_label = match session.kind { CollectionKind::DirectoryBrowser => "DirectoryBrowser",
CollectionKind::DirectoryBrowser => "DirectoryBrowser", CollectionKind::DocumentCollection => "DocumentCollection",
CollectionKind::DocumentCollection => "DocumentCollection", };
println!(
" {MAGENTA}Session: {BOLD}{}{RESET} {DIM}({kind_label}, {} items, active: {:?}){RESET}",
session.name,
session.items.len(),
active_doc_index,
);
for (i, item) in session.items.iter().enumerate() {
let marker = if active_doc_index == Some(i) {
format!("{GREEN}=>{RESET}")
} else {
format!("{DIM} {RESET}")
}; };
let name = item
.path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("?");
println!( println!(
" {MAGENTA}Collection: {BOLD}{}{RESET} {DIM}({kind_label}, {} items, index: {:?}){RESET}", " {marker} {DIM}[{i}]{RESET} {name} {DIM}(page {}){RESET}",
session.name, item.page_index
session.items.len(),
session.current_index
); );
for (i, item) in session.items.iter().enumerate() {
let marker = if session.current_index == Some(i) {
format!("{GREEN}=>{RESET}")
} else {
format!("{DIM} {RESET}")
};
let name = item
.path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("?");
println!(
" {marker} {DIM}[{i}]{RESET} {name} {DIM}(page {}){RESET}",
item.page_index
);
}
} else {
err(&format!("Session '{session_name}' not found"));
} }
} }
@ -82,9 +78,11 @@ fn exec(manager: &mut DocumentManager, label: &str, command: SessionCommand) {
} }
} }
fn print_nav_index(manager: &DocumentManager, label: &str) { fn print_active_session(mgr: &DocumentManager) {
if let Some(session) = manager.active_session() { if let Some(session) = mgr.active_session() {
ok(&format!("{label:<28} → index {:?}", session.current_index)); print_session(session, mgr.active_document_index());
} else {
info("No active session");
} }
} }
@ -98,7 +96,6 @@ fn print_nav_index(manager: &DocumentManager, label: &str) {
.args(["open_document", "open_directory", "open_session"]) .args(["open_document", "open_directory", "open_session"])
) )
)] )]
struct Opt { struct Opt {
/// Open a document (raster, vector, portable) /// Open a document (raster, vector, portable)
#[arg(long, value_name = "PATH")] #[arg(long, value_name = "PATH")]
@ -119,12 +116,16 @@ fn main() {
let cli = Opt::parse(); let cli = Opt::parse();
let mut mgr = DocumentManager::new(); let mut mgr = DocumentManager::new();
// ── Open source ── // Open source
heading("Opening source"); heading("Opening source");
if let Some(path) = cli.open_session { if let Some(path) = cli.open_session {
exec(&mut mgr, "Open session file", SessionCommand::Open { path }); exec(
&mut mgr,
"Open session file",
SessionCommand::OpenSession { path },
);
} else if let Some(path) = cli.open_document { } else if let Some(path) = cli.open_document {
let dir = path let dir = path
.parent() .parent()
@ -139,28 +140,27 @@ fn main() {
exec( exec(
&mut mgr, &mut mgr,
&format!("New browser session '{session_name}'"), &format!("New session '{session_name}'"),
SessionCommand::New { SessionCommand::NewSession {
name: session_name.clone(), name: session_name.clone(),
kind: CollectionKind::DirectoryBrowser,
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
&format!("Select '{session_name}'"), &format!("Select '{session_name}'"),
SessionCommand::Select { SessionCommand::SelectSession {
name: session_name.clone(), name: session_name.clone(),
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
&format!("Add directory {}", dir.display()), &format!("Add directory {}", dir.display()),
SessionCommand::AddDirectory { dir }, SessionCommand::AddDirectoryToSession { dir },
); );
exec( exec(
&mut mgr, &mut mgr,
&format!("Add document {}", path.display()), &format!("Add document {}", path.display()),
SessionCommand::AddDocument { path }, SessionCommand::AddDocumentToSession { path },
); );
} else if let Some(path) = cli.open_directory { } else if let Some(path) = cli.open_directory {
let session_name = path let session_name = path
@ -172,26 +172,25 @@ fn main() {
exec( exec(
&mut mgr, &mut mgr,
&format!("New session '{session_name}'"), &format!("New session '{session_name}'"),
SessionCommand::New { SessionCommand::NewSession {
name: session_name.clone(), name: session_name.clone(),
kind: CollectionKind::DirectoryBrowser,
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
&format!("Select '{session_name}'"), &format!("Select '{session_name}'"),
SessionCommand::Select { SessionCommand::SelectSession {
name: session_name.clone(), name: session_name.clone(),
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
&format!("Add directory {}", path.display()), &format!("Add directory {}", path.display()),
SessionCommand::AddDirectory { dir: path }, SessionCommand::AddDirectoryToSession { dir: path },
); );
} }
// ── State summary ── // State summary
heading("State after open"); heading("State after open");
@ -202,7 +201,7 @@ fn main() {
DocumentState::Loaded(_) => ok("Document loaded"), DocumentState::Loaded(_) => ok("Document loaded"),
} }
let active_name = match mgr.active_session_name.clone() { let active_name = match mgr.active_session().map(|s| s.name.clone()) {
Some(n) => n, Some(n) => n,
None => { None => {
info("No active session nothing more to test."); info("No active session nothing more to test.");
@ -210,115 +209,189 @@ fn main() {
} }
}; };
print_session(&mgr, &active_name); print_active_session(&mgr);
// ── Navigation ── // Navigation
heading("Navigation"); heading("Navigation");
exec(&mut mgr, "NextDocument", SessionCommand::NextDocument); exec(&mut mgr, "NextDocument", SessionCommand::NextDocument);
print_nav_index(&mgr, "After NextDocument"); ok(&format!(
"After NextDocument → index {:?}",
mgr.active_document_index()
));
exec( exec(
&mut mgr, &mut mgr,
"PreviousDocument", "PreviousDocument",
SessionCommand::PreviousDocument, SessionCommand::PreviousDocument,
); );
print_nav_index(&mgr, "After PreviousDocument"); ok(&format!(
"After PreviousDocument → index {:?}",
mgr.active_document_index()
));
exec( exec(
&mut mgr, &mut mgr,
"SelectDocument { index: 0 }", "SelectDocument { index: 0 }",
SessionCommand::SelectDocument { index: 0 }, SessionCommand::SelectDocument { index: 0 },
); );
print_nav_index(&mgr, "After SelectDocument(0)"); ok(&format!(
"After SelectDocument(0) → index {:?}",
mgr.active_document_index()
));
// ── Collection operations ── // Move operations
heading("Collection operations"); heading("Move operations");
step("Before MoveDocumentDown:");
print_active_session(&mgr);
exec(
&mut mgr,
"MoveDocumentDown",
SessionCommand::MoveDocumentDown,
);
ok(&format!(
"After MoveDocumentDown → index {:?}",
mgr.active_document_index()
));
exec(&mut mgr, "MoveDocumentUp", SessionCommand::MoveDocumentUp);
ok(&format!(
"After MoveDocumentUp → index {:?}",
mgr.active_document_index()
));
// Copy / Paste
heading("Copy / Paste");
exec( exec(
&mut mgr, &mut mgr,
"New session 'Favorites'", "New session 'Favorites'",
SessionCommand::New { SessionCommand::NewSession {
name: "Favorites".to_string(), name: "Favorites".to_string(),
kind: CollectionKind::DocumentCollection,
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
"New session 'Workspace'", "New session 'Workspace'",
SessionCommand::New { SessionCommand::NewSession {
name: "Workspace".to_string(), name: "Workspace".to_string(),
kind: CollectionKind::DocumentCollection,
}, },
); );
// Copy first item from browser → Favorites step("Favorites before paste:");
heading("Copy item to Favorites"); if let Some(session) = mgr.session_by_name("Favorites") {
step("Before:"); print_session(session, None);
print_session(&mgr, "Favorites"); }
// SelectSession source → SelectDocument → CopyDocument → SelectSession target → PasteDocument
exec( exec(
&mut mgr, &mut mgr,
&format!("Copy [0] from '{active_name}' → 'Favorites'"), &format!("SelectSession '{active_name}'"),
SessionCommand::CopyDocument { SessionCommand::SelectSession {
source: active_name.clone(),
target: "Favorites".to_string(),
source_index: 0,
target_index: 0,
},
);
step("After:");
print_session(&mgr, "Favorites");
// Remove from DirectoryBrowser (should fail)
heading("Remove from DirectoryBrowser (expect error)");
exec(
&mut mgr,
&format!("Select '{active_name}'"),
SessionCommand::Select {
name: active_name.clone(), name: active_name.clone(),
}, },
); );
exec( exec(
&mut mgr, &mut mgr,
"RemoveDocument { index: 0 }", "SelectDocument { index: 0 }",
SessionCommand::RemoveDocument { index: 0 }, SessionCommand::SelectDocument { index: 0 },
); );
exec(&mut mgr, "CopyDocument", SessionCommand::CopyDocument);
// Move: Favorites → Workspace (copy + delete)
heading("Move: Favorites → Workspace");
step("Before:");
print_session(&mgr, "Favorites");
print_session(&mgr, "Workspace");
exec( exec(
&mut mgr, &mut mgr,
"Copy [0] from 'Favorites' → 'Workspace'", "SelectSession 'Favorites'",
SessionCommand::CopyDocument { SessionCommand::SelectSession {
source: "Favorites".to_string(),
target: "Workspace".to_string(),
source_index: 0,
target_index: 0,
},
);
exec(
&mut mgr,
"Select 'Favorites'",
SessionCommand::Select {
name: "Favorites".to_string(), name: "Favorites".to_string(),
}, },
); );
exec(&mut mgr, "PasteDocument", SessionCommand::PasteDocument);
step("Favorites after paste:");
print_active_session(&mgr);
// Move pasted item to front via MoveDocumentTo
exec( exec(
&mut mgr, &mut mgr,
"RemoveDocument { index: 0 }", "MoveDocumentTo { index: 0 }",
SessionCommand::RemoveDocument { index: 0 }, SessionCommand::MoveDocumentTo { index: 0 },
);
step("Favorites after MoveDocumentTo(0):");
print_active_session(&mgr);
// Remove active document
exec(&mut mgr, "RemoveDocument", SessionCommand::RemoveDocument);
step("Favorites after RemoveDocument:");
print_active_session(&mgr);
// Session operations
heading("Session operations");
exec(
&mut mgr,
&format!("SelectSession '{active_name}'"),
SessionCommand::SelectSession {
name: active_name.clone(),
},
);
exec(
&mut mgr,
"DuplicateSession 'Snapshot'",
SessionCommand::DuplicateSession {
new_name: "Snapshot".to_string(),
},
); );
step("After:"); step("Snapshot session:");
print_session(&mgr, "Favorites"); if let Some(session) = mgr.session_by_name("Snapshot") {
print_session(&mgr, "Workspace"); print_session(session, None);
}
exec(
&mut mgr,
"SelectSession 'Workspace'",
SessionCommand::SelectSession {
name: "Workspace".to_string(),
},
);
exec(
&mut mgr,
"RenameSession 'Archive'",
SessionCommand::RenameSession {
name: "Archive".to_string(),
},
);
step("All sessions after rename:");
for session in mgr.sessions() {
let is_active = mgr
.active_session()
.map_or(false, |a| a.name == session.name);
let marker = if is_active {
format!("{GREEN}*{RESET}")
} else {
format!("{DIM} {RESET}")
};
println!(" {marker} {}", session.name);
}
exec(
&mut mgr,
"CloseSession (closes 'Archive')",
SessionCommand::CloseSession,
);
step("All sessions after close:");
for session in mgr.sessions() {
println!(" {DIM}-{RESET} {}", session.name);
}
heading("Done"); heading("Done");
} }