Make interactive output go to the terminal (bug #17213), by
authorBen Pfaff <blp@gnu.org>
Fri, 27 Jul 2007 22:58:02 +0000 (22:58 +0000)
committerBen Pfaff <blp@gnu.org>
Fri, 27 Jul 2007 22:58:02 +0000 (22:58 +0000)
causing the UI to flush output to the user when it prompts for a
command.
Thanks to John Darrington for review.

19 files changed:
config/ChangeLog
config/devices
src/data/ChangeLog
src/data/file-name.c
src/data/settings.c
src/libpspp/ChangeLog
src/libpspp/automake.mk
src/libpspp/getl.c
src/output/ChangeLog
src/output/ascii.c
src/output/html.c
src/output/manager.c
src/output/manager.h
src/output/output.c
src/output/output.h
src/output/postscript.c
src/ui/terminal/ChangeLog
src/ui/terminal/command-line.c
src/ui/terminal/read-line.c

index 292a289f249c1f50745c1e46971840bc58a7c79a..b5f672a3ed05b5c5867a65e9d996aa85854a8fb4 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-25  Ben Pfaff  <blp@gnu.org>
+
+       * devices: Add an "interactive" category that defaults to
+       tty-ascii.  Make the tty-ascii device more user-friendly.
+
 Tue Apr  4 20:20:49 2006  Ben Pfaff  <blp@gnu.org>
 
        * automake.mk: Fix bugs in installation targets.
index 94cba3af833d6d17ae7b7368a0aa82787c0eb90c..ab96d66d7a77ffa0472a0914f721c435d08dc4b5 100644 (file)
 # referenced with $var or ${var} syntax; the latter is preferred.
 
 # Preferred devices.
-default=tty list
-tty=#tty-ibmpc
-list=list-ascii
+default=list-ascii
+interactive=tty-ascii
 
 # Output files.
-define tty-output-file "/dev/tty"
+define tty-output-file "|more"
 define list-output-file "pspp.list"
 
 # Generic ASCII devices
-tty-ascii:ascii:screen:output-file=${tty-output-file}
+tty-ascii:ascii:screen:squeeze=on headers=off top-margin=0 bottom-margin=0 \
+  paginate=off length=${viewlength} width=${viewwidth} \
+  output-file=${tty-output-file}
 list-ascii:ascii:listing:length=66 width=79 output-file=${list-output-file}
 raw-ascii:ascii:screen:width=9999 length=9999 output-file=${list-output-file} \
   emphasis=none headers=off paginate=off squeeze=on \
index ddf6e685bc51c2f64cb02812381853a1860e3891..326517109177cb979cf4d8c13cd57cd63b709601 100644 (file)
@@ -1,3 +1,17 @@
+2007-07-25  Ben Pfaff  <blp@gnu.org>
+
+       Fix bugs related to bug #17213.
+
+       * settings.c: Use HAVE_LIBNCURSES instead of HAVE_LIBTERMCAP,
+       since the former is what config.h has.  Include the needed ncurses
+       headers.
+       (static var echo) Rename to `do_echo' because the original name is
+       the same as an ncurses identifier.
+       (get_termcap_viewport) Use error instead of msg.
+
+       * file-name.c (fn_interp_vars): Fix interpolation of $VARS.
+       (fn_close): Don't close stdin, stdout, stderr.
+
 2007-07-26 John Darrington <john@darrington.wattle.id.au>
 
        * procedure.c procedure.h: Added callbacks which get invoked whenever 
index 2ad3311a2dfb3c2824df8009d18b16f843540bd6..23d7ee0889f2c75460e8d479eb177b7acc2f75d9 100644 (file)
@@ -87,7 +87,7 @@ fn_interp_vars (struct substring src, const char *(*getenv) (const char *),
             else if (ss_match_char (&src, '{'))
               ss_get_until (&src, '}', &var_name);
             else
-              ss_get_chars (&src, MIN (1, ss_span (src, ss_cstr (CC_ALNUM))),
+              ss_get_chars (&src, MAX (1, ss_span (src, ss_cstr (CC_ALNUM))),
                             &var_name);
 
             start = ds_length (&dst);
@@ -305,7 +305,9 @@ fn_open (const char *fn, const char *mode)
 int
 fn_close (const char *fn, FILE *f)
 {
-  if (!strcmp (fn, "-"))
+  if (fileno (f) == STDIN_FILENO
+      || fileno (f) == STDOUT_FILENO
+      || fileno (f) == STDERR_FILENO)
     return 0;
 #if HAVE_POPEN
   else if (fn[0] == '|' || (*fn && fn[strlen (fn) - 1] == '|'))
index 3e95b6b5bfd3bf64eec1dd8d17471c9d29ea0d84..b14fb618f3a235addab2a140270dae0a7149f0aa 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007 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
 #include "xalloc.h"
 #include <libpspp/i18n.h>
 
+#include "error.h"
+
+#ifdef HAVE_LIBNCURSES
+#include <curses.h>
+#include <term.h>
+#endif
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 static int viewlength = 24;
 static int viewwidth = 79;
 static bool long_view = false;
 
 static bool safer_mode = false;
 
-static bool echo = false;
+static bool do_echo = false;
 static bool include = true;
 
 static int epoch = -1;
@@ -121,7 +131,7 @@ set_viewwidth (int viewwidth_)
   viewwidth = viewwidth_;
 }
 
-#if HAVE_LIBTERMCAP
+#if HAVE_LIBNCURSES
 static void
 get_termcap_viewport (void)
 {
@@ -130,7 +140,8 @@ get_termcap_viewport (void)
     return;
   else if (tgetent (term_buffer, getenv ("TERM")) <= 0)
     {
-      msg (IE, _("Could not access definition for terminal `%s'."), termtype);
+      error (0,0, _("could not access definition for terminal `%s'"),
+             getenv ("TERM"));
       return;
     }
 
@@ -140,7 +151,7 @@ get_termcap_viewport (void)
   if (tgetnum ("co") > 1)
     viewwidth = tgetnum ("co") - 1;
 }
-#endif /* HAVE_LIBTERMCAP */
+#endif /* HAVE_LIBNCURSES */
 
 static void
 init_viewport (void)
@@ -150,9 +161,9 @@ init_viewport (void)
 
   viewwidth = viewlength = -1;
 
-#if HAVE_LIBTERMCAP
+#if HAVE_LIBNCURSES
   get_termcap_viewport ();
-#endif /* HAVE_LIBTERMCAP */
+#endif /* HAVE_LIBNCURSES */
 
   if (viewwidth < 0 && getenv ("COLUMNS") != NULL)
     viewwidth = atoi (getenv ("COLUMNS"));
@@ -183,14 +194,14 @@ set_safer_mode (void)
 bool
 get_echo (void)
 {
-  return echo;
+  return do_echo;
 }
 
 /* Set echo. */
 void
 set_echo (bool echo_)
 {
-  echo = echo_;
+  do_echo = echo_;
 }
 
 /* If echo is on, whether commands from include files are echoed. */
index e0cebfb85ccd02328da9f90cba570c515f4db5a2..6f3ddf519d23e9068b6cc970962eff23ac905dc5 100644 (file)
@@ -1,3 +1,11 @@
+2007-07-25  Ben Pfaff  <blp@gnu.org>
+
+       * getl.c (getl_append_source): Add source to *end* of list.
+       Otherwise the list ends up in reverse order.
+
+       * automake.mk (src/libpspp/version.c): Use $HOME instead of ~ in
+       paths.  We don't interpolate ~.
+
 2007-07-22  Ben Pfaff  <blp@gnu.org>
 
        * str.h: Include xstrndup.h also.
index ca6b7195b160243265e93302ee26b884ac584d08..e0914c950c2f8e9b347c35e600953a1742f06690 100644 (file)
@@ -89,9 +89,9 @@ src/libpspp/version.c: $(top_srcdir)/AUTHORS
        echo "const char host_system[] = \"$(host_triplet)\";" >> $@
        echo "const char build_system[] = \"$(build_triplet)\";" >> $@
        echo "const char default_config_path[] =\
-\"~/.pspp:$(pkgsysconfdir)\";" >> $@
+\"\$$HOME/.pspp:$(pkgsysconfdir)\";" >> $@
        echo "const char include_path[] =\
-\"./:~/.pspp/include:$(pkgdatadir)\";" >> $@
+\"./:\$$HOME/.pspp/include:$(pkgdatadir)\";" >> $@
        echo "const char locale_dir[] = \"$(datadir)/locale\";" >> $@
        echo "const char *const authors[] = {" >> $@
        sed -e 's/^/  \"/' -e 's/$$/\",/' $(top_srcdir)/AUTHORS >> $@
index dbabde478ed7952b8f69c1e16de8765357ef3504..b4617122677840ecd65a9670a3d424e3f03964d6 100644 (file)
@@ -94,7 +94,7 @@ getl_append_source (struct source_stream *ss, struct getl_interface *i)
 
   s->interface = i ;
 
-  ll_push_head (&ss->sources, &s->ll);
+  ll_push_tail (&ss->sources, &s->ll);
 }
 
 /* Nests source S within the current source file. */
index a5e3cf4943f6b79d095e710ef6bacad7a70a1343..5b0318f7f106b211246b7867030d01abd74c30e8 100644 (file)
@@ -1,3 +1,22 @@
+2007-07-25  Ben Pfaff  <blp@gnu.org>
+
+       Make interactive output go to the terminal (bug #17213), by
+       causing the UI to flush output to the user when it prompts for a
+       command.
+
+       * ascii.c (ascii_open_driver): Move the file open into
+       ascii_open_page, so that we can re-open after a flush.
+       (ascii_close_driver): Close file using ascii_flush.
+       (ascii_open_page): Open the output file if it's not already open.
+       Use fn_open so that we can support pipes.
+       (ascii_close_page): Do nothing if output file not open.
+       (ascii_flush): New function.
+       (static var ascii_class): Add ascii_flush.
+
+       * manager.c (som_flush): New function.
+
+       * output.c (outp_flush): New function.
+
 Tue Feb 20 07:03:48 2007  Ben Pfaff  <blp@gnu.org>
 
        * html.c: Don't need to include "getlogin_r.h" anymore, because
index 8ed4f918fed26b4929084275001371d579910a33..f1d5a9be47791c7d9ea8dce7ac5b59167cc07095 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
@@ -115,6 +115,7 @@ struct ascii_driver_ext
     int line_cap;               /* Number of lines allocated. */
   };
 
+static void ascii_flush (struct outp_driver *);
 static int get_default_box_char (size_t idx);
 static bool handle_option (struct outp_driver *this, const char *key,
                            const struct string *val);
@@ -152,13 +153,6 @@ ascii_open_driver (struct outp_driver *this, struct substring options)
   if (!outp_parse_options (options, handle_option, this))
     goto error;
 
-  x->file = pool_fopen (x->pool, x->file_name, "w");
-  if (x->file == NULL)
-    {
-      error (0, errno, _("ascii: opening output file \"%s\""), x->file_name);
-      goto error;
-    }
-
   this->length = x->page_length - x->top_margin - x->bottom_margin - 1;
   if (x->headers)
     this->length -= 3;
@@ -226,8 +220,7 @@ ascii_close_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
 
-  if (fn_close (x->file_name, x->file) != 0)
-    error (0, errno, _("ascii: closing output file \"%s\""), x->file_name);
+  ascii_flush (this);
   pool_detach_file (x->pool, x->file);
   pool_destroy (x->pool);
 
@@ -410,6 +403,18 @@ ascii_open_page (struct outp_driver *this)
   struct ascii_driver_ext *x = this->ext;
   int i;
 
+  if (x->file == NULL)
+    {
+      x->file = fn_open (x->file_name, "w");
+      if (x->file == NULL)
+        {
+          error (0, errno, _("ascii: opening output file \"%s\""),
+                 x->file_name);
+          return;
+        }
+      pool_attach_file (x->pool, x->file);
+    }
+
   x->page_number++;
 
   if (this->length > x->line_cap)
@@ -670,6 +675,9 @@ ascii_close_page (struct outp_driver *this)
   struct string out;
   int line_num;
 
+  if (x->file == NULL)
+    return;
+
   ds_init_empty (&out);
 
   ds_put_char_multiple (&out, '\n', x->top_margin);
@@ -718,6 +726,25 @@ ascii_close_page (struct outp_driver *this)
   ds_destroy (&out);
 }
 
+/* Flushes all output to the user and lets the user deal with it.
+   This is applied only to output drivers that are designated as
+   "screen" drivers that the user is interacting with in real
+   time. */
+static void
+ascii_flush (struct outp_driver *this)
+{
+  struct ascii_driver_ext *x = this->ext;
+
+  if (x->file != NULL)
+    {
+      if (fn_close (x->file_name, x->file) != 0)
+        error (0, errno, _("ascii: closing output file \"%s\""),
+               x->file_name);
+      pool_detach_file (x->pool, x->file);
+      x->file = NULL;
+    }
+}
+
 static void
 ascii_chart_initialise (struct outp_driver *d UNUSED, struct chart *ch)
 {
@@ -741,6 +768,7 @@ const struct outp_class ascii_class =
 
   ascii_open_page,
   ascii_close_page,
+  ascii_flush,
 
   NULL,
 
index e07edec8773d8044ed96ee35a134fdfb0646812e..b938333fe9464b71451eba5ac4f9f74c99b5c76d 100644 (file)
@@ -405,6 +405,7 @@ const struct outp_class html_class =
     html_open_driver,
     html_close_driver,
 
+    NULL,
     NULL,
     NULL,
 
index 2d16416aef49ded08f92e457a7d8ea153ed7bf9f..0b2fdfe1cf2ab53fc1fdaaf4ce3decf23b14f0ad 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
@@ -47,6 +47,16 @@ som_eject_page (void)
     outp_eject_page (d);
 }
 
+/* Flushes output on all active devices. */
+void
+som_flush (void)
+{
+  struct outp_driver *d;
+
+  for (d = outp_drivers (NULL); d; d = outp_drivers (d))
+    outp_flush (d);
+}
+
 /* Skip down a single line on all active devices. */
 void
 som_blank_line (void)
index ce658311ae157392de9599f0372c7e61cf98838e..58d0c12d48594862a7e838b0f8f3ee52b50fa605 100644 (file)
@@ -114,5 +114,6 @@ void som_submit (struct som_entity *t);
 /* Miscellaneous. */
 void som_eject_page (void);
 void som_blank_line (void);
+void som_flush (void);
 
 #endif /* som_h */
index dea3e4ad243a5359499adfa55ecb5deb21c5db63..243e7cd3f2805db1bd7c9d978540d778bc79a031 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
@@ -150,8 +150,8 @@ add_name (char *bp, char *ep, int source)
   outp_configure_vec = n;
 }
 
-/* Checks that outp_configure_vec is empty, bitches & clears it if it
-   isn't. */
+/* Checks that outp_configure_vec is empty, complains and clears
+   it if it isn't. */
 static void
 check_configure_vec (void)
 {
@@ -701,7 +701,7 @@ configure_driver (struct substring driver_name, struct substring class_name,
   d->class = c->class;
   d->name = ss_xstrdup (driver_name);
   d->page_open = false;
-  d->device = OUTP_DEV_NONE;
+  d->device = device;
   d->cp_x = d->cp_y = 0;
   d->ext = NULL;
   d->prc = NULL;
@@ -1143,6 +1143,18 @@ outp_eject_page (struct outp_driver *d)
   outp_open_page (d);
 }
 
+/* Flushes output to screen devices, so that the user can see
+   output that doesn't fill up an entire page. */
+void
+outp_flush (struct outp_driver *d)
+{
+  if (d->device & OUTP_DEV_SCREEN && d->class->flush != NULL)
+    {
+      outp_close_page (d);
+      d->class->flush (d);
+    }
+}
+
 /* Returns the width of string S, in device units, when output on
    device D. */
 int
index 32ad6cef96f4d1946a10535f0ff8e26b109f2005..7215cb6ca3797cb3f006437a9278791ed503854e 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
@@ -73,6 +73,8 @@ struct outp_class
     void (*open_page) (struct outp_driver *);
     void (*close_page) (struct outp_driver *);
 
+    void (*flush) (struct outp_driver *);
+
     /* special != 0 only. */
     void (*submit) (struct outp_driver *, struct som_entity *);
 
@@ -155,6 +157,7 @@ bool outp_get_paper_size (char *, int *h, int *v);
 void outp_open_page (struct outp_driver *);
 void outp_close_page (struct outp_driver *);
 void outp_eject_page (struct outp_driver *);
+void outp_flush (struct outp_driver *);
 
 int outp_string_width (struct outp_driver *, const char *, enum outp_font);
 
index 6046b0fd8d7bdc86fb4edacbafe99089482ce537..f49970c5b0875014b5b638b3dd28635e8ac860be 100644 (file)
@@ -1433,6 +1433,7 @@ const struct outp_class postscript_class =
 
   ps_open_page,
   ps_close_page,
+  NULL,
 
   ps_submit,
 
index 10d7d36558ba7f729c7d4e01610108b3561804c5..a98b9244aa0affea65d68e4a8ba0fdadba203360 100644 (file)
@@ -1,3 +1,15 @@
+2007-07-25  Ben Pfaff  <blp@gnu.org>
+
+       Make interactive output go to the terminal (bug #17213), by
+       causing the UI to flush output to the user when it prompts for a
+       command.
+
+       * command-line.c (parse_command_line): Configure interactive
+       output devices if appropriate.
+
+       * read-line.c (readln_read): Flush output if this is a prompt for
+       the first line of a command.
+
 2007-06-06  Ben Pfaff  <blp@gnu.org>
 
        Adapt case sources, sinks, and clients of procedure code to the
index 9eb23d5319f8a021aee53d71d189ff005553efab..e152f7009992eb55ad6194bddb62d4efd323488e 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-void welcome (void);
 static void usage (void);
 
-char *subst_vars (char *);
-
-
 /* Parses the command line specified by ARGC and ARGV as received by
    main().  Returns true if normal execution should proceed,
    false if the command-line indicates that PSPP should exit. */
@@ -209,7 +205,11 @@ parse_command_line (int argc, char **argv, struct source_stream *ss)
       }
 
   if (!syntax_files || interactive_mode)
-    getl_append_source (ss, create_readln_source () );
+    {
+      getl_append_source (ss, create_readln_source () );
+      if (!cleared_device_defaults)
+        outp_configure_add ("interactive");
+    }
 
   return true;
 }
index e361832680964e41d413970be213ba24071241a8..c6279ce9c4bd6514ee797ed034d498bcdfdd671b 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
@@ -32,6 +32,7 @@
 #include <libpspp/str.h>
 #include <libpspp/version.h>
 #include <language/prompt.h>
+#include <output/manager.h>
 
 #include "xalloc.h"
 
@@ -148,6 +149,9 @@ readln_read (struct string *line, enum prompt_style style)
 
   welcome ();
 
+  if (style == PROMPT_FIRST)
+    som_flush ();
+
 #if HAVE_READLINE
   rl_attempted_completion_function = (style == PROMPT_FIRST
                                       ? complete_command_name