I've created a patch which adds support for troff "-ms" output to
authorBruce Momjian <bruce@momjian.us>
Thu, 9 Jun 2005 15:27:27 +0000 (15:27 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 9 Jun 2005 15:27:27 +0000 (15:27 +0000)
psql.  i.e. "\pset format troff-ms".  The patch also corrects some
problems with the "latex" format, notably defining an extra column in
the output table, and correcting some alignment issues; it also
changes the output to match the border setting as documented in the
manual page and as shown with the "aligned" format.

The troff-ms output is mostly identical to the latex output allowing
for the differences between the two typesetters.

The output should be saved in a file and piped as follows:

  cat file | tbl | troff -T ps -ms > file.ps
or
  tbl file | troff -T ps -ms > file.ps

Because it contains tabs, you'll need to redirect psql output or use
"script", rather than pasting from a terminal window, due to the tabs
which can be replaced with spaces.

Roger Leigh

doc/src/sgml/ref/psql-ref.sgml
src/bin/psql/command.c
src/bin/psql/print.c
src/bin/psql/print.h

index bc762ab7c18bbafb9772fb147e1b6041c32e45eb..148fd0807dc34e9ea47882168a80eef65fd48bf3 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.138 2005/06/02 01:23:48 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.139 2005/06/09 15:27:26 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -1386,9 +1386,10 @@ lo_import 152801
           <listitem>
           <para>
           Sets the output format to one of <literal>unaligned</literal>,
-          <literal>aligned</literal>, <literal>html</literal>, or
-          <literal>latex</literal>. Unique abbreviations are allowed.
-          (That would mean one letter is enough.)
+          <literal>aligned</literal>, <literal>html</literal>,
+          <literal>latex</literal>, or <literal>troff-ms</literal>.
+          Unique abbreviations are allowed.  (That would mean one letter
+     is enough.)
           </para>
 
           <para>
index 7523f67eb6317e95096042e4a91d5d019893eee1..5b646ee130fb3df21b093747ba696b22059e8524 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.143 2005/04/29 13:42:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.144 2005/06/09 15:27:26 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -1357,6 +1357,9 @@ _align2string(enum printFormat in)
        case PRINT_LATEX:
            return "latex";
            break;
+       case PRINT_TROFF_MS:
+           return "troff-ms";
+           break;
    }
    return "unknown";
 }
@@ -1385,9 +1388,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
            popt->topt.format = PRINT_HTML;
        else if (pg_strncasecmp("latex", value, vallen) == 0)
            popt->topt.format = PRINT_LATEX;
+       else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
+           popt->topt.format = PRINT_TROFF_MS;
        else
        {
-           psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n");
+           psql_error("\\pset: allowed formats are unaligned, aligned, html, latex, troff-ms\n");
            return false;
        }
 
index 1321e99582b80e7c68b28dc73e82fdf806235de9..e08486241706d7855658a41584bce4e6f0b5fda6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.55 2005/02/22 04:40:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.56 2005/06/09 15:27:27 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "common.h"
@@ -992,6 +992,213 @@ const char *opt_align, bool opt_barebones, unsigned short int opt_border,
 
 
 
+/*************************/
+/* Troff -ms        */
+/*************************/
+
+
+static void
+troff_ms_escaped_print(const char *in, FILE *fout)
+{
+   const char *p;
+
+   for (p = in; *p; p++)
+       switch (*p)
+       {
+           case '\\':
+               fputs("\(rs", fout);
+               break;
+           default:
+               fputc(*p, fout);
+       }
+}
+
+
+
+static void
+print_troff_ms_text(const char *title, const char *const * headers,
+                const char *const * cells, const char *const * footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+                FILE *fout)
+{
+   unsigned int col_count = 0;
+   unsigned int i;
+   const char *const * ptr;
+
+
+   /* print title */
+   if (!opt_barebones && title)
+   {
+       fputs(".LP\n.DS C\n", fout);
+       troff_ms_escaped_print(title, fout);
+       fputs("\n.DE\n", fout);
+   }
+
+   /* count columns */
+   for (ptr = headers; *ptr; ptr++)
+       col_count++;
+
+   /* begin environment and set alignments and borders */
+   fputs(".LP\n.TS\n", fout);
+   if (opt_border == 2)
+       fputs("center box;\n", fout);
+   else
+       fputs("center;\n", fout);
+
+   for (i = 0; i < col_count; i++)
+   {
+       fputc(*(opt_align + i), fout);
+       if (opt_border > 0 && i < col_count - 1)
+           fputs(" | ", fout);
+   }
+   fputs(".\n", fout);
+
+   /* print headers and count columns */
+   for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+   {
+       if (!opt_barebones)
+       {
+           if (i != 0)
+               fputc('\t', fout);
+           fputs("\\fI", fout);
+           troff_ms_escaped_print(*ptr, fout);
+           fputs("\\fP", fout);
+       }
+   }
+
+   if (!opt_barebones)
+   {
+       fputs("\n_\n", fout);
+   }
+
+   /* print cells */
+   for (i = 0, ptr = cells; *ptr; i++, ptr++)
+   {
+       troff_ms_escaped_print(*ptr, fout);
+
+       if ((i + 1) % col_count == 0)
+           fputc('\n', fout);
+       else
+           fputc('\t', fout);
+   }
+
+   fputs(".TE\n.DS L\n", fout);
+
+
+   /* print footers */
+
+   if (footers && !opt_barebones)
+       for (ptr = footers; *ptr; ptr++)
+       {
+           troff_ms_escaped_print(*ptr, fout);
+           fputc('\n', fout);
+       }
+
+   fputs(".DE\n", fout);
+}
+
+
+
+static void
+print_troff_ms_vertical(const char *title, const char *const * headers,
+                 const char *const * cells, const char *const * footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+                    FILE *fout)
+{
+   unsigned int col_count = 0;
+   unsigned int i;
+   const char *const * ptr;
+   unsigned int record = 1;
+        unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
+
+   (void) opt_align;           /* currently unused parameter */
+
+   /* print title */
+   if (!opt_barebones && title)
+   {
+       fputs(".LP\n.DS C\n", fout);
+       troff_ms_escaped_print(title, fout);
+       fputs("\n.DE\n", fout);
+   }
+
+   /* begin environment and set alignments and borders */
+   fputs(".LP\n.TS\n", fout);
+   if (opt_border == 2)
+       fputs("center box;\n", fout);
+   else
+       fputs("center;\n", fout);
+
+   /* basic format */
+        if (opt_barebones)
+       fputs("c l;\n", fout);
+
+
+   /* count columns */
+   for (ptr = headers; *ptr; ptr++)
+       col_count++;
+
+
+   /* print records */
+   for (i = 0, ptr = cells; *ptr; i++, ptr++)
+   {
+       /* new record */
+       if (i % col_count == 0)
+       {
+           if (!opt_barebones)
+           {
+
+               if (current_format != 1)
+               {
+                   if (opt_border == 2 && i > 0)
+                       fputs("_\n", fout);
+                   if (current_format != 0)
+                       fputs(".T&\n", fout);
+                   fputs("c s.\n", fout);
+                   current_format = 1;
+               }
+               fprintf(fout, "\\fIRecord %d\\fP\n", record++);
+           }
+           if (opt_border >= 1)
+               fputs("_\n", fout);
+       }
+
+       if (!opt_barebones)
+       {
+           if (current_format != 2)
+           {
+               if (current_format != 0)
+                   fputs(".T&\n", fout);
+               if (opt_border != 1)
+                   fputs("c l.\n", fout);
+               else
+                   fputs("c | l.\n", fout);
+               current_format = 2;
+           }
+       }
+
+       troff_ms_escaped_print(headers[i % col_count], fout);
+       fputc('\t', fout);
+       troff_ms_escaped_print(*ptr, fout);
+       fputc('\n', fout);
+   }
+
+   fputs(".TE\n.DS L\n", fout);
+
+
+   /* print footers */
+
+   if (footers && !opt_barebones)
+       for (ptr = footers; *ptr; ptr++)
+       {
+           troff_ms_escaped_print(*ptr, fout);
+           fputc('\n', fout);
+       }
+
+   fputs(".DE\n", fout);
+}
+
+
+
 /********************************/
 /* Public functions        */
 /********************************/
@@ -1121,6 +1328,12 @@ printTable(const char *title,
            else
                print_latex_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
            break;
+       case PRINT_TROFF_MS:
+           if (opt->expanded)
+               print_troff_ms_vertical(title, headers, cells, footers, align, opt->tuples_only, border, output);
+           else
+               print_troff_ms_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
+           break;
        default:
            fprintf(stderr, "+ Oops, you shouldn't see this!\n");
    }
index b30d302883a739445899ce6e4b5404395170209a..8560ebd737f17084f571e3b05bc90b7441d1fb4f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.22 2005/01/01 05:43:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.23 2005/06/09 15:27:27 momjian Exp $
  */
 #ifndef PRINT_H
 #define PRINT_H
@@ -21,7 +21,8 @@ enum printFormat
    PRINT_UNALIGNED,
    PRINT_ALIGNED,
    PRINT_HTML,
-   PRINT_LATEX
+   PRINT_LATEX,
+   PRINT_TROFF_MS
    /* add your favourite output format here ... */
 };