Move toward having output drivers.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 4 Jan 2025 03:29:42 +0000 (19:29 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 4 Jan 2025 03:29:42 +0000 (19:29 -0800)
rust/pspp/src/output/csv.rs [new file with mode: 0644]
rust/pspp/src/output/driver.rs [new file with mode: 0644]
rust/pspp/src/output/mod.rs
rust/pspp/src/output/page.rs [new file with mode: 0644]
rust/pspp/src/output/pivot/mod.rs

diff --git a/rust/pspp/src/output/csv.rs b/rust/pspp/src/output/csv.rs
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/rust/pspp/src/output/driver.rs b/rust/pspp/src/output/driver.rs
new file mode 100644 (file)
index 0000000..89d0bac
--- /dev/null
@@ -0,0 +1,64 @@
+use std::{borrow::Cow, sync::Arc};
+
+use chrono::format::Item;
+
+use super::page::Setup;
+
+// An output driver.
+pub trait Driver {
+    fn name(&self) -> Cow<'static, &str>;
+
+    fn write(&mut self, item: Arc<Item>);
+
+    /// Returns false if the driver doesn't support page setup.
+    fn setup(&mut self, page_setup: &Setup) -> bool;
+
+    /// Ensures that anything written with [Self::write] has been displayed.
+    ///
+    /// This is called from the text-based UI before showing the command prompt,
+    /// to ensure that the user has actually been shown any preceding output If
+    /// it doesn't make sense for this driver to be used this way, then this
+    /// function need not do anything.
+    fn flush(&mut self);
+
+    /// Ordinarily, the core driver code will skip passing hidden output items
+    /// to [Self::write].  If this returns true, the core driver hands them to
+    /// the driver to let it handle them itself.
+    fn handles_show(&self) -> bool {
+        false
+    }
+
+    /// Ordinarily, the core driver code will flatten groups of output items
+    /// before passing them to [Self::write].  If this returns true, the core
+    /// driver code leaves them in place for the driver to handle.
+    fn handles_groups(&self) -> bool {
+        false
+    }
+}
+
+/*
+/// An abstract way for the output subsystem to create an output driver.
+trait DriverFactory {
+    /// The file extension, without the leading dot, e.g. "pdf".
+    fn extension(&self) ->  OsString;
+
+    /// The default file name, including extension.
+    ///
+    /// If this is `-`, that implies that by default output will be directed to
+    /// stdout.
+    fn default_file_name(&self) -> PathBuf;
+
+    /// Creates a new output driver of this class.  `name` and `type` should be
+    /// passed directly to output_driver_init.
+    ///
+    /// It is up to the driver class to decide how to interpret `options`.  The
+    /// create function should delete pairs that it understands from `options`,
+    /// because the caller may issue errors about unknown options for any pairs
+    /// that remain.
+    fn create(&self, file_handle: (),
+              
+                                     enum settings_output_devices type,
+                                     struct driver_options *);
+
+}
+*/
index f16da89f4f006f9ee21edb917dea9f136c712c90..b26a42a170efb060889cec850a99b0dc27e99d3b 100644 (file)
@@ -1,8 +1,13 @@
 #![allow(dead_code)]
 use std::sync::Arc;
 
+use pivot::PivotTable;
+
 use self::pivot::Value;
 
+pub mod csv;
+pub mod driver;
+pub mod page;
 pub mod pivot;
 pub mod table;
 
@@ -35,8 +40,8 @@ pub enum Details {
     Image,
     Group(Vec<Arc<Item>>),
     Message,
-    Table,
-    Text(Text),
+    Table(Box<PivotTable>),
+    Text(Box<Text>),
 }
 
 pub struct Text {
diff --git a/rust/pspp/src/output/page.rs b/rust/pspp/src/output/page.rs
new file mode 100644 (file)
index 0000000..f36cab0
--- /dev/null
@@ -0,0 +1,76 @@
+use std::path::PathBuf;
+
+use enum_map::{enum_map, EnumMap};
+
+use super::pivot::{Axis2, HorzAlign};
+
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub enum Orientation {
+    #[default]
+    Portrait,
+    Landscape,
+}
+
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub enum ChartSize {
+    #[default]
+    AsIs,
+    FullHeight,
+    HalfHeight,
+    QuarterHeight,
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct Paragraph {
+    pub markup: String,
+    pub horz_align: HorzAlign,
+}
+
+impl Default for Paragraph {
+    fn default() -> Self {
+        Self {
+            markup: Default::default(),
+            horz_align: HorzAlign::Left,
+        }
+    }
+}
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct Heading(pub Vec<Paragraph>);
+
+pub struct Setup {
+    pub initial_page_number: i32,
+
+    /// Paper size in inches.
+    pub paper: EnumMap<Axis2, f64>,
+
+    /// Margin width in inches.
+    pub margins: EnumMap<Axis2, [f64; 2]>,
+
+    pub orientation: Orientation,
+
+    /// Space between objects, in inches.
+    pub object_spacing: f64,
+
+    pub chart_size: ChartSize,
+
+    /// Header and footer.
+    pub headings: [Heading; 2],
+
+    file_name: Option<PathBuf>,
+}
+
+impl Default for Setup {
+    fn default() -> Self {
+        Self {
+            initial_page_number: 1,
+            paper: enum_map! { Axis2::X => 8.5, Axis2::Y => 11.0 },
+            margins: enum_map! { Axis2::X => [0.5, 0.5], Axis2::Y => [0.5, 0.5] },
+            orientation: Default::default(),
+            object_spacing: 12.0 / 72.0,
+            chart_size: Default::default(),
+            headings: Default::default(),
+            file_name: None,
+        }
+    }
+}
index c3af6c182269a5c25a46bdf48def8bcf1573ee7f..c69b6d57affd4c40f3912415524a00d411cc4488 100644 (file)
@@ -592,7 +592,7 @@ pub struct CellStyle {
     margins: EnumMap<Axis2, [i32; 2]>,
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum HorzAlign {
     /// Right aligned.
     Right,