From 5d936c2d48d25f3619456d8d513477374d518bca Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 31 Dec 2025 17:04:10 -0800 Subject: [PATCH] work --- rust/pspp/src/cli/show_spv.rs | 52 ++++++++++++++++++----------- rust/pspp/src/output.rs | 33 ++++++++++++------ rust/pspp/src/spv.rs | 2 +- rust/pspp/src/spv/read.rs | 2 +- rust/pspp/src/spv/read/structure.rs | 13 ++++++-- 5 files changed, 67 insertions(+), 35 deletions(-) diff --git a/rust/pspp/src/cli/show_spv.rs b/rust/pspp/src/cli/show_spv.rs index d60219997f..eeeeb92761 100644 --- a/rust/pspp/src/cli/show_spv.rs +++ b/rust/pspp/src/cli/show_spv.rs @@ -22,7 +22,11 @@ use pspp::{ Criteria, Item, Itemlike, SpvMembers, pivot::{Axis3, Dimension, Group, Leaf, PivotTable, value::Value}, }, - spv::{SpvArchive, legacy_bin::LegacyBin}, + spv::{ + SpvArchive, + legacy_bin::LegacyBin, + read::{ReadSeek, structure::OutlineItem}, + }, }; use std::{ collections::HashMap, @@ -122,9 +126,15 @@ impl ShowSpv { )) } + fn read_outline(&self) -> Result<(SpvArchive>, Vec>)> { + let mut archive = SpvArchive::open_file(&self.input, self.password.as_deref())?; + let outline = archive.read_outline(|w| eprintln!("{w}"))?; + Ok((archive, self.criteria.apply(outline.items))) + } + fn directory(self) -> Result<()> { - for child in self.read()? { - print_item_directory(&child, 0, self.show_member_names); + for child in self.read_outline()?.1 { + print_item_directory(&*child, 0, self.show_member_names); } Ok(()) } @@ -137,9 +147,7 @@ impl ShowSpv { } fn legacy_data(self) -> Result<()> { - let mut archive = SpvArchive::open_file(&self.input, self.password.as_deref())?; - let outline = archive.read_outline(|w| eprintln!("{w}"))?; - let items = self.criteria.apply(outline.items); + let (mut archive, items) = self.read_outline()?; for item in items { for item in item.iter_in_order() { if let Some(spv_info) = item.spv_info() @@ -199,39 +207,43 @@ impl ShowSpv { } } -fn print_item_directory(item: &Item, level: usize, show_member_names: bool) { +fn print_item_directory(item: &T, level: usize, show_member_names: bool) +where + T: Itemlike, +{ for _ in 0..level { print!(" "); } - print!("- {} {:?}", item.details.kind(), item.label()); + print!("- {} {:?}", item.kind(), item.label()); + /* if let Some(table) = item.details.as_table() { let title = table.title().display(table).to_string(); if item.label.as_ref().is_none_or(|label| label != &title) { print!(" title {title:?}"); } - } - if let Some(command_name) = &item.command_name { + }*/ + if let Some(command_name) = item.command_name() { print!(" command {command_name:?}"); } if let Some(subtype) = item.subtype() - && item.label.as_ref().is_none_or(|label| label != &subtype) + && let label = item.label().as_ref() + && label != &subtype { print!(" subtype {subtype:?}"); } - if !item.show { - if item.details.is_heading() { - print!(" (collapsed)"); - } else { - print!(" (hidden)"); - } + if item.is_expanded() == Some(false) { + print!(" (collapsed"); + } + if item.is_shown() == Some(false) { + print!(" (hidden)"); } - if show_member_names && let Some(spv_info) = &item.spv_info { + if show_member_names && let Some(spv_info) = item.spv_info() { for (index, name) in spv_info.member_names().into_iter().enumerate() { print!(" {} {name:?}", if index == 0 { "in" } else { "and" }); } } println!(); - for child in item.details.children() { - print_item_directory(&child, level + 1, show_member_names); + for child in item.children() { + print_item_directory(&**child, level + 1, show_member_names); } } diff --git a/rust/pspp/src/output.rs b/rust/pspp/src/output.rs index a2f1d69532..83da04e000 100644 --- a/rust/pspp/src/output.rs +++ b/rust/pspp/src/output.rs @@ -87,7 +87,7 @@ pub trait Itemlike { fn label(&self) -> Cow<'_, str>; fn command_name(&self) -> Option<&str>; fn subtype(&self) -> Option; - fn is_shown(&self) -> bool; + fn is_shown(&self) -> Option; fn page_break_before(&self) -> bool; fn spv_info(&self) -> Option>; fn iter_in_order(&self) -> ItemRefIterator<'_, Self> @@ -99,6 +99,7 @@ pub trait Itemlike { fn is_heading(&self) -> bool { self.kind() == ItemKind::Heading } + fn is_expanded(&self) -> Option; fn is_table(&self) -> bool { self.kind() == ItemKind::Table } @@ -148,10 +149,22 @@ impl Itemlike for Item { /// Should the item be shown? /// - /// This always returns true for headings because their contents are always - /// shown (although headings can be collapsed in an outline view). - fn is_shown(&self) -> bool { - self.details.is_heading() || self.show + /// This returns None for headings because their contents are always shown + /// (although headings can be collapsed in an outline view). + fn is_shown(&self) -> Option { + if !self.details.is_heading() { + Some(self.show) + } else { + None + } + } + + fn is_expanded(&self) -> Option { + if self.details.is_heading() { + Some(self.show) + } else { + None + } } fn page_break_before(&self) -> bool { @@ -591,7 +604,7 @@ impl<'a, T> ItemRefIterator<'a, T> { where T: Itemlike, { - self.filter(|item| item.is_shown()) + self.filter(|item| item.is_shown().unwrap_or(true)) } pub fn new(start: &'a T) -> Self { @@ -638,7 +651,7 @@ where { pub fn new(start: Arc) -> Self { Self { - cur: start.as_ref().is_shown().then_some(start), + cur: start.as_ref().is_shown().unwrap_or(true).then_some(start), stack: Vec::new(), include_hidden: false, } @@ -680,7 +693,7 @@ where inner(self); while let Some(cur) = &self.cur - && !cur.as_ref().is_shown() + && !cur.as_ref().is_shown().unwrap_or(true) { inner(self); } @@ -1044,8 +1057,8 @@ impl Criteria { continue; } if let Some(visible) = selection.visible - && !item.is_heading() - && visible != item.is_shown() + && let Some(shown) = item.is_shown() + && visible != shown { continue; } diff --git a/rust/pspp/src/spv.rs b/rust/pspp/src/spv.rs index eb26aaf501..17990f94fc 100644 --- a/rust/pspp/src/spv.rs +++ b/rust/pspp/src/spv.rs @@ -27,7 +27,7 @@ // Warn about missing docs, but not for items declared with `#[cfg(test)]`. #![cfg_attr(not(test), warn(missing_docs))] -mod read; +pub mod read; mod write; pub use read::{Error, SpvArchive, SpvFile, SpvOutline, html, legacy_bin}; diff --git a/rust/pspp/src/spv/read.rs b/rust/pspp/src/spv/read.rs index 2c0fd94432..fb5daf70cf 100644 --- a/rust/pspp/src/spv/read.rs +++ b/rust/pspp/src/spv/read.rs @@ -39,7 +39,7 @@ pub mod html; pub mod legacy_bin; mod legacy_xml; mod light; -mod structure; +pub mod structure; #[cfg(test)] mod tests; diff --git a/rust/pspp/src/spv/read/structure.rs b/rust/pspp/src/spv/read/structure.rs index 231c1e906f..a4b18eb037 100644 --- a/rust/pspp/src/spv/read/structure.rs +++ b/rust/pspp/src/spv/read/structure.rs @@ -155,10 +155,17 @@ impl Itemlike for OutlineItem { } } - fn is_shown(&self) -> bool { + fn is_shown(&self) -> Option { match self { - OutlineItem::Heading(_) => true, - OutlineItem::Container(container) => container.show, + OutlineItem::Heading(_) => None, + OutlineItem::Container(container) => Some(container.show), + } + } + + fn is_expanded(&self) -> Option { + match self { + OutlineItem::Heading(outline_heading) => Some(outline_heading.expand), + OutlineItem::Container(_) => None, } } -- 2.30.2