Implement the SET SUMMARY command
authorJohn Darrington <john@cellform.com>
Wed, 7 Jun 2023 15:45:35 +0000 (17:45 +0200)
committerJohn Darrington <john@cellform.com>
Wed, 7 Jun 2023 15:59:03 +0000 (17:59 +0200)
NEWS
doc/utilities.texi
src/data/settings.c
src/data/settings.h
src/language/commands/set.c
src/output/pivot-table.c
tests/language/commands/set.at

diff --git a/NEWS b/NEWS
index 5465ec695babd6b0224d79a39c5e36d7dc67644a..8bcb526ffa3beba4b72ebaac5ececdb6f0975b7a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ Changes from 1.6.2 to 2.0.0-pre1:
 
  * DISPLAY MACROS is now implemented.
 
+ * SET SUMMARY is now implemented.
+
  * SHOW ENVIRONMENT is now implemented.
 
  * Removed the MODIFY VARS command, which is not in SPSS.
index 6b752fbc031abd698519e05f5c139c623c2f79d5..f4aed354646fe4143ed79c72cc7824ec451805e0 100644 (file)
@@ -1,5 +1,5 @@
 @c PSPP - a program for statistical analysis.
-@c Copyright (C) 2017, 2020 Free Software Foundation, Inc.
+@c Copyright (C) 2017, 2020, 2023 Free Software Foundation, Inc.
 @c Permission is granted to copy, distribute and/or modify this document
 @c under the terms of the GNU Free Documentation License, Version 1.3
 @c or any later version published by the Free Software Foundation;
@@ -510,6 +510,7 @@ SET
         /LEADZERO=@{ON,OFF@}
         /MDISPLAY=@{TEXT,TABLES@}
         /SMALL=@var{number}
+        /SUMMARY=@{NONE,@var{comment}@}
         /WIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@}
         /WRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@}
 
@@ -780,6 +781,31 @@ set here, @pspp{} formats the number in scientific notation;
 otherwise, it formats it in standard notation.  The default is 0.0001.
 Set a value of 0 to disable scientific notation.
 
+@item SUMMARY
+The @subcmd{SUMMARY} option sets the comment string which will appear in all
+generated tables until the next @subcmd{SUMMARY} is issued.  If the special
+value @subcmd{NONE} is specified, then no comment will appear.
+These comment strings can be seen in the graphical user interface by placing
+the pointer over the table.
+If @var{comment} contains any of the following substrings, they will be
+subsituted as follows:
+@table @code
+@item \n
+A line break.
+@item )DATE
+The current date in the form @samp{dd-mmm-yyyy}
+@item )ADATE
+The current date in the form @samp{mm/dd/yyyy}
+@item )SDATE
+The current date in the form @samp{yyyy/mm/dd}
+@item )EDATE
+The current date in the form @samp{dd.mm.yyyy}
+@item )TIME
+The current 12 hour clock time in the form @samp{hh:mm:ss}
+@item )ETIME
+The current 24 hour clock time in the form @samp{hh:mm:ss}
+@end table
+
 @item WIB
 @anchor{SET WIB}
 
index d4ed848a7e7336f47159debe4852a30ae027c82a..7e34a60ad406a813c9015677afbaae7c12354b26 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015, 2023 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -87,6 +87,8 @@ struct settings
 
   enum settings_value_show show_values;
   enum settings_value_show show_variables;
+
+  char *table_summary;
 };
 
 static struct settings the_settings = {
@@ -129,6 +131,7 @@ static struct settings the_settings = {
   .syntax = ENHANCED,
   .styles = FMT_SETTINGS_INIT,
   .small = .0001,
+  .table_summary = 0,
 
   /* output_routing */
   .output_routing = {
@@ -190,6 +193,7 @@ settings_destroy (struct settings *s)
   if (s != NULL)
     {
       fmt_settings_uninit (&s->styles);
+      free (s->table_summary);
       if (s != &the_settings)
         free (s);
     }
@@ -640,6 +644,26 @@ settings_get_fmt_settings (void)
   return &the_settings.styles;
 }
 
+char *
+settings_get_summary (void)
+{
+  return the_settings.table_summary;
+}
+
+void
+settings_set_summary (const char *s)
+{
+  free (the_settings.table_summary);
+
+  if (s == NULL)
+    {
+      the_settings.table_summary = NULL;
+      return;
+    }
+
+  the_settings.table_summary = xstrdup (s);
+}
+
 double
 settings_get_small (void)
 {
index 76988b2719c73dc70bf169060d5dced39ab4bf28..21b3f6cb3850d089097ce675f437dd27e0015ab4 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2015 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2015, 2023 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -165,6 +165,9 @@ const struct fmt_settings *settings_get_fmt_settings (void);
 double settings_get_small (void);
 void settings_set_small (double);
 
+char * settings_get_summary (void);
+void settings_set_summary (const char *s);
+
 char *settings_dollar_template (struct fmt_spec);
 
 /* Routing of different kinds of output. */
index 5994228c7c004c32e5d42b723df5ae4cd4485a1f..b05ce691b4a2731d685d6af35dc7ba2a294a6564 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2023 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -936,6 +936,34 @@ parse_SEED (struct lexer *lexer)
   return true;
 }
 
+
+static bool
+parse_SUMMARY (struct lexer *lexer)
+{
+  lex_match (lexer, T_EQUALS);
+
+  if (lex_match_id (lexer, "NONE"))
+    {
+      settings_set_summary (NULL);
+      return true;
+    }
+
+  if (!lex_force_string (lexer))
+    return false;
+
+  const char *s = lex_tokcstr (lexer);
+  settings_set_summary (s);
+  lex_get (lexer);
+
+  return true;
+}
+
+static char *
+show_SUMMARY (const struct dataset *ds UNUSED)
+{
+  return settings_get_summary ();
+}
+
 static bool
 parse_SMALL (struct lexer *lexer)
 {
@@ -1314,6 +1342,7 @@ static const struct setting settings[] = {
   { "SEED", parse_SEED, NULL },
   { "SMALL", parse_SMALL, show_SMALL },
   { "SPLIT", NULL, show_SPLIT },
+  { "SUMMARY", parse_SUMMARY, show_SUMMARY },
   { "TEMPDIR", NULL, show_TEMPDIR },
   { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
   { "TVARS", parse_TVARS, show_TVARS },
index a8f70ca6232c21fcc091d35348087f49e7346906..c2113c623d3989114fbf2e989309768f891c3458 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2017, 2018 Free Software Foundation, Inc.
+   Copyright (C) 2017, 2018, 2023 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,6 +44,7 @@
 #include "gl/xalloc.h"
 #include "gl/xmemdup0.h"
 #include "gl/xsize.h"
+#include "time.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -850,6 +851,96 @@ pivot_table_create (const char *title)
   return pivot_table_create__ (pivot_value_new_text (title), title);
 }
 
+static const char *mtable[12] =
+  {"jan", "feb", "mar", "apr", "may", "jun",
+   "jul", "aug", "sep", "oct", "nov", "dec"};
+
+/* Expand S replacing expressions as necessary */
+static char *summary_expansion (const char *s)
+{
+  if (!s || !s[0])
+    return NULL;
+
+  struct string comment;
+  ds_init_empty (&comment);
+  time_t now = time (NULL);
+  struct tm *lt = localtime (&now);
+  while (*s)
+    {
+      switch (*s)
+        {
+        case ')':
+          if (0 == strncmp (s + 1, "DATE", 4))
+            {
+              s += 4;
+              if (lt)
+                ds_put_c_format (&comment, "%02d-%s-%04d",
+                                 lt->tm_mday, mtable[lt->tm_mon], lt->tm_year + 1900);
+            }
+          else if (0 == strncmp (s + 1, "ADATE", 5))
+            {
+              s += 5;
+              if (lt)
+                ds_put_c_format (&comment, "%02d/%02d/%04d",
+                                 lt->tm_mon + 1, lt->tm_mday, lt->tm_year + 1900);
+            }
+          else if (0 == strncmp (s + 1, "SDATE", 5))
+            {
+              s += 5;
+              if (lt)
+                ds_put_c_format (&comment, "%04d/%02d/%02d",
+                                 lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday);
+            }
+          else if (0 == strncmp (s + 1, "EDATE", 5))
+            {
+              s += 5;
+              if (lt)
+                ds_put_c_format (&comment, "%02d.%02d.%04d",
+                                 lt->tm_mday, lt->tm_mon + 1, lt->tm_year + 1900);
+            }
+          else if (0 == strncmp (s + 1, "TIME", 4))
+            {
+              s += 4;
+              if (lt)
+                {
+                  /* 12 hour time format */
+                  int hour = lt->tm_hour % 12;
+                  if (hour == 0)
+                    hour = 12;
+                  ds_put_c_format (&comment, "%02d:%02d:%02d",
+                                   hour, lt->tm_min, lt->tm_sec);
+                }
+            }
+          else if (0 == strncmp (s + 1, "ETIME", 5))
+            {
+              s += 5;
+              if (lt)
+                ds_put_c_format (&comment, "%02d:%02d:%02d",
+                                 lt->tm_hour, lt->tm_min, lt->tm_sec);
+            }
+          break;
+        case '\\':
+          if (s[1] == 'n')
+            {
+              s++;
+              ds_put_byte (&comment, '\n');
+            }
+          break;
+        default:
+          ds_put_byte (&comment, *s);
+          break;
+        }
+      s++;
+    }
+
+  char *string = ds_steal_cstr (&comment);
+
+  ds_destroy (&comment);
+
+  return string;
+}
+
+
 /* Creates and returns a new pivot table with the given TITLE, and takes
    ownership of TITLE.  The new pivot table's subtype is SUBTYPE, which should
    be an untranslated English string that describes the contents of the table
@@ -871,6 +962,7 @@ pivot_table_create__ (struct pivot_value *title, const char *subtype)
     .show_caption = true,
     .weight_format = (struct fmt_spec) { .type = FMT_F, .w = 40 },
     .title = title,
+    .notes = summary_expansion (settings_get_summary ()),
     .subtype = subtype ? pivot_value_new_text (subtype) : NULL,
     .command_c = xstrdup_if_nonempty (output_get_command_name ()),
     .look = pivot_table_look_ref (pivot_table_look_get_default ()),
index cd8a1020f71e73922ad90a118eadb623c233484d..9ee8509672ee4b6d2f2f4f7840d2fb77455613c0 100644 (file)
@@ -1,5 +1,5 @@
 dnl PSPP - a program for statistical analysis.
-dnl Copyright (C) 2017 Free Software Foundation, Inc.
+dnl Copyright (C) 2017, 2023 Free Software Foundation, Inc.
 dnl
 dnl This program is free software: you can redistribute it and/or modify
 dnl it under the terms of the GNU General Public License as published by
@@ -202,6 +202,7 @@ SET SCOMPRESSION=**.
 SET SEED=**.
 SET SMALL=**.
 SET SUBTITLE=**.
+SET SUMMARY=**.
 SET TNUMBERS=**.
 SET TVARS=**.
 SET TLOOK='nonexistent.xml'.
@@ -384,34 +385,38 @@ AT_CHECK([pspp -O format=csv set.sps], [1], [dnl
    43 | SET SUBTITLE=**.
       |     ^~~~~~~~"
 
-"set.sps:44.14-44.15: error: SET: Syntax error expecting LABELS, VALUES, or BOTH.
-   44 | SET TNUMBERS=**.
+"set.sps:44.13-44.14: error: SET: Syntax error expecting string.
+   44 | SET SUMMARY=**.
+      |             ^~"
+
+"set.sps:45.14-45.15: error: SET: Syntax error expecting LABELS, VALUES, or BOTH.
+   45 | SET TNUMBERS=**.
       |              ^~"
 
-"set.sps:45.11-45.12: error: SET: Syntax error expecting LABELS, NAMES, or BOTH.
-   45 | SET TVARS=**.
+"set.sps:46.11-46.12: error: SET: Syntax error expecting LABELS, NAMES, or BOTH.
+   46 | SET TVARS=**.
       |           ^~"
 
-set.sps:46: error: SET: nonexistent.xml: not found
+set.sps:47: error: SET: nonexistent.xml: not found
 
-"set.sps:47.15-47.16: error: SET: Syntax error expecting WARN or NOWARN.
-   47 | SET UNDEFINED=**.
+"set.sps:48.15-48.16: error: SET: Syntax error expecting WARN or NOWARN.
+   48 | SET UNDEFINED=**.
       |               ^~"
 
-"set.sps:48.9-48.10: error: SET: Syntax error expecting MSBFIRST, LSBFIRST, VAX, or NATIVE.
-   48 | SET WIB=**.
+"set.sps:49.9-49.10: error: SET: Syntax error expecting MSBFIRST, LSBFIRST, VAX, or NATIVE.
+   49 | SET WIB=**.
       |         ^~"
 
-"set.sps:49.9-49.10: error: SET: Syntax error expecting one of the following: NATIVE, ISL, ISB, IDL, IDB, VF, VD, VG, ZS.
-   49 | SET WRB=**.
+"set.sps:50.9-50.10: error: SET: Syntax error expecting one of the following: NATIVE, ISL, ISB, IDL, IDB, VF, VD, VG, ZS.
+   50 | SET WRB=**.
       |         ^~"
 
-"set.sps:50.11-50.12: error: SET: Syntax error expecting integer 40 or greater for WIDTH.
-   50 | SET WIDTH=**.
+"set.sps:51.11-51.12: error: SET: Syntax error expecting integer 40 or greater for WIDTH.
+   51 | SET WIDTH=**.
       |           ^~"
 
-"set.sps:51.15-51.16: error: SET: Syntax error expecting integer 1024 or greater for WORKSPACE.
-   51 | SET WORKSPACE=**.
+"set.sps:52.15-52.16: error: SET: Syntax error expecting integer 1024 or greater for WORKSPACE.
+   52 | SET WORKSPACE=**.
       |               ^~"
 ])
 AT_CLEANUP