Change style for footnote markers in text output.
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 9 Jan 2026 15:41:35 +0000 (07:41 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 9 Jan 2026 15:41:35 +0000 (07:41 -0800)
rust/doc/src/commands/set.md
rust/doc/src/language/datasets/formats/basic.md
rust/pspp/src/output/pivot/testdata/footnote_alphabetic_subscript.expected
rust/pspp/src/output/pivot/testdata/footnote_alphabetic_superscript.expected
rust/pspp/src/output/pivot/testdata/footnote_hidden.expected
rust/pspp/src/output/pivot/testdata/footnote_numeric_subscript.expected
rust/pspp/src/output/pivot/testdata/footnote_numeric_superscript.expected
rust/pspp/src/output/pivot/value.rs
rust/pspp/src/spv/testdata/legacy16.expected
rust/pspp/src/spv/testdata/legacy9.expected

index 774f57e1974d98d2403587dc2112483684cabd68..bf0b0bb82c138f693f434986358bfbb779aa7d66 100644 (file)
@@ -255,8 +255,8 @@ subcommands are
 * <a name="leadzero">`LEADZERO`</a>  
   Controls whether numbers with magnitude less than one are displayed
   with a zero before the decimal point.  For example, with `SET
-  LEADZERO=OFF`, which is the default, one-half is shown as 0.5, and
-  with `SET LEADZERO=ON`, it is shown as .5.  This setting affects
+  LEADZERO=OFF`, which is the default, one-half is shown as `0.5`, and
+  with `SET LEADZERO=ON`, it is shown as `.5`.  This setting affects
   only the `F`, `COMMA`, and `DOT` formats.
 
 * <a name="mdisplay">`MDISPLAY`</a>  
index 6f9aa47dbc33045884ddcc517b82cff8dd241025..7d46bf297ca0a346d914ed9c91559eb3ee8c426d 100644 (file)
@@ -122,15 +122,25 @@ More details of basic numeric output formatting are given below:
   preferred to ordinary decimal notation without it.
 
 - Except in scientific notation, a decimal point is included only when
-  it is followed by a digit.  If the integer part of the number being
-  output is 0, and a decimal point is included, then PSPP ordinarily
-  drops the zero before the decimal point.  However, in `F`, `COMMA`,
-  or `DOT` formats, PSPP keeps the zero if [`SET
-  LEADZERO`](../../../commands/set.md#leadzero) is set to
-  `ON`.
-
-  In scientific notation, the number always includes a decimal point,
-  even if it is not followed by a digit.
+  it is followed by a digit.  In scientific notation, the number
+  always includes a decimal point, even if it is not followed by a
+  digit.
+
+- If the integer part of the number being output is 0, and a decimal
+  point is included, whether PSPP displays the zero before the decimal
+  point depends on the following factors:
+
+  - For `F`, `COMMA`, or `DOT` formats, PSPP keeps the leading zero if
+    [`SET LEADZERO`](../../../commands/set.md#leadzero) is set to
+    `ON`.
+
+  - For `PCT` and `DOLLAR`, PSPP drops the leading zero unless the
+    number is being output within a pivot table in PSPP output[^0].
+
+    [^0]: There is a further exception: PSPP drops the leading zero if
+    the number is being output within a pivot table as part of a
+    templated longer text string rather than as a number on its own.
+    These currently only appear in SPV files written by SPSS.
 
 - A negative number includes a minus sign only in the presence of a
   nonzero digit: -0.01 is output as `-.01` in `F4.2` format but as
index 4878aa099cfa691e66b9f8a72d554c95ff171f12..b394e850bbf2528395988e5d758820c62a8fe5eb 100644 (file)
@@ -1,12 +1,12 @@
 Pivot Table with Alphabetic Subscript Footnotes[*]
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80─────────────────╮
-│            │       A[*]       │
-│            ├───────┬──────────┤
-│Corner[*][b]│  B[b] │  C[*][b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┤
-│D[b] E[*]   │    .00│   1.00[*]│
-│     F[*][b]│2.00[b]│3.00[*][b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬─────────────────╮
+│           │       A[*]      │
+│           ├───────┬─────────┤
+│Corner[*,b]│  B[b] │  C[*,b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┤
+│D[b] E[*]  │    .00│  1.00[*]│
+│     F[*,b]│2.00[b]│3.00[*,b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────╯
 Caption[*]
 *. First footnote
 b. Second footnote
index c989f62f8a089a993e23d619c4a683e0475dd44f..73475f75d461fd420c72df965154bbb85ff8394e 100644 (file)
@@ -1,12 +1,12 @@
 Pivot Table with Alphabetic Superscript Footnotes[*]
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80─────────────────╮
-│            │       A[*]       │
-│            ├───────┬──────────┤
-│Corner[*][b]│  B[b] │  C[*][b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┤
-│D[b] E[*]   │    .00│   1.00[*]│
-│     F[*][b]│2.00[b]│3.00[*][b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬─────────────────╮
+│           │       A[*]      │
+│           ├───────┬─────────┤
+│Corner[*,b]│  B[b] │  C[*,b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┤
+│D[b] E[*]  │    .00│  1.00[*]│
+│     F[*,b]│2.00[b]│3.00[*,b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────╯
 Caption[*]
 *. First footnote
 b. Second footnote
index ce76a3f630228a1ba8fef346e821df75efa2b1e0..b67a8c98d3f85f84fbf0282b87ac24f8249ffb7c 100644 (file)
@@ -1,11 +1,11 @@
 Pivot Table with Alphabetic Subscript Footnotes[*]
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80─────────────────╮
-│            │       A[*]       │
-│            ├───────┬──────────┤
-│Corner[*][b]│  B[b] │  C[*][b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┤
-│D[b] E[*]   │    .00│   1.00[*]│
-│     F[*][b]│2.00[b]│3.00[*][b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬─────────────────╮
+│           │       A[*]      │
+│           ├───────┬─────────┤
+│Corner[*,b]│  B[b] │  C[*,b] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┤
+│D[b] E[*]  │    .00│  1.00[*]│
+│     F[*,b]│2.00[b]│3.00[*,b]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────╯
 Caption[*]
 b. Second footnote
index 82c1ccf6790260e5980816370213eb7cd7fdb480..6a466006fe19dc34eb834549eede15ffb4eefb8d 100644 (file)
@@ -1,12 +1,12 @@
 Pivot Table with Numeric Subscript Footnotes[*]
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80─────────────────╮
-│            │       A[*]       │
-│            ├───────┬──────────┤
-│Corner[*][2]│  B[2] │  C[*][2] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┤
-│D[2] E[*]   │    .00│   1.00[*]│
-│     F[*][2]│2.00[2]│3.00[*][2]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬─────────────────╮
+│           │       A[*]      │
+│           ├───────┬─────────┤
+│Corner[*,2]│  B[2] │  C[*,2] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┤
+│D[2] E[*]  │    .00│  1.00[*]│
+│     F[*,2]│2.00[2]│3.00[*,2]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────╯
 Caption[*]
 *. First footnote
 2. Second footnote
index c6498624cc04cfe962e083884af89becdebc2170..27a25e63fa6c32601aa7aac953f51a99d87aeedd 100644 (file)
@@ -1,12 +1,12 @@
 Pivot Table with Numeric Superscript Footnotes[*]
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80─────────────────╮
-│            │       A[*]       │
-│            ├───────┬──────────┤
-│Corner[*][2]│  B[2] │  C[*][2] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┤
-│D[2] E[*]   │    .00│   1.00[*]│
-│     F[*][2]│2.00[2]│3.00[*][2]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬─────────────────╮
+│           │       A[*]      │
+│           ├───────┬─────────┤
+│Corner[*,2]│  B[2] │  C[*,2] │
\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┤
+│D[2] E[*]  │    .00│  1.00[*]│
+│     F[*,2]│2.00[2]│3.00[*,2]│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────╯
 Caption[*]
 *. First footnote
 2. Second footnote
index aad9a9543daf39697ce782501fe0d12fa6dfbcd6..fe88f63c50c4c577a050025be494ab70862249e1 100644 (file)
@@ -36,6 +36,7 @@ use crate::{
     variable::{VarType, Variable},
 };
 use chrono::{NaiveDateTime, NaiveTime};
+use itertools::Itertools;
 use serde::{
     Serialize, Serializer,
     ser::{SerializeMap, SerializeStruct},
@@ -612,8 +613,15 @@ impl Display for DisplayValue<'_> {
             write!(f, "{delimiter}{subscript}")?;
         }
 
-        for footnote in self.footnotes {
-            write!(f, "[{}]", footnote.display_marker(&self.options))?;
+        if !self.footnotes.is_empty() {
+            write!(
+                f,
+                "[{}]",
+                self.footnotes
+                    .iter()
+                    .map(|f| f.display_marker(&self.options))
+                    .format(",")
+            )?;
         }
 
         Ok(())
index b8cf7896bc0eb0177bf4374950471d8878becd8c..11a74d319c52ed466a42ac2c7ef17018115a9247 100644 (file)
@@ -11,7 +11,7 @@
 │       Refused       AGE│59.0[1]│.                 │50.0[1]│.                 │54.5│               6.4│
 │       Total         AGE│   52.1│               9.1│   51.8│              10.7│51.9│              10.0│
 ╰────────────────────────┴───────┴──────────────────┴───────┴──────────────────┴────┴──────────────────╯
-Note: Values in the same row and subtable not sharing the same subscript are significantly different at p< 0.05 in the two-sided test of equality for column means. Cells with no subscript are not included in the test. Tests assume equal variances.[2][3]
+Note: Values in the same row and subtable not sharing the same subscript are significantly different at p< 0.05 in the two-sided test of equality for column means. Cells with no subscript are not included in the test. Tests assume equal variances.[2,3]
 1.  This category is not used in comparisons because the sum of case weights is less than two.
 2.  Tests are adjusted for all pairwise comparisons within a row of each innermost subtable using the Bonferroni correction.
 3.  Pairwise comparisons are not performed for some subtables because of numerical problems.
index 9e88b6901c4bcafc4a32985b957bb3c240222e2a..dfbcded95d094dcad59541607a753858b3249d6d 100644 (file)
@@ -1,5 +1,5 @@
     Analysis
-Test: Duncan[a][b]
+Test: Duncan[a,b]
        │ Subset
 SP36  N│   1
 ───────┼───────