Add a latex-longtable output format to psql
authorBruce Momjian
Thu, 17 Jan 2013 16:39:38 +0000 (11:39 -0500)
committerBruce Momjian
Thu, 17 Jan 2013 16:39:38 +0000 (11:39 -0500)
latex longtable is more powerful than the 'tabular' output format
'latex' uses.  Also add border=3 support to 'latex'.

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

index c41593c5e3669464d52048a4eace2ca9da1ca3c3..504a5164de9dc0c04ddf02cbc7a7e46da2d232e7 100644 (file)
@@ -1890,6 +1890,9 @@ lo_import 152801
           into the border=... attribute; in the
           other formats only values 0 (no border), 1 (internal dividing lines),
           and 2 (table frame) make sense.
+          latex and latex-longtable
+          also support a border value of 3 which adds
+          a dividing line between each row.
           
           
           
@@ -1979,7 +1982,9 @@ lo_import 152801
           Sets the output format to one of unaligned,
           alignedwrapped,
           html,
-          latex, or troff-ms.
+          latex (uses tabular),
+          latex-longtable, or
+          troff-ms.
           Unique abbreviations are allowed.  (That would mean one letter
           is enough.)
           
@@ -2005,12 +2010,16 @@ lo_import 152801
           
 
           
-          The html, latex, and troff-ms
+          The html, latex,
+          latex-longtable, and troff-ms
           formats put out tables that are intended to
           be included in documents using the respective mark-up
-          language. They are not complete documents! (This might not be
-          so dramatic in HTML, but in LaTeX you must
-          have a complete document wrapper.)
+          language. They are not complete documents! This might not be
+          necessary in HTML, but in
+          LaTeX you must have a complete
+          document wrapper.  latex-longtable
+          also requires the LaTeX
+          longtable and booktabs packages.
           
           
           
@@ -2141,9 +2150,8 @@ lo_import 152801
           tableattr (or T)
           
           
-          Specifies attributes to be placed inside the
-          HTML table tag in
-          html output format. This
+          In HTML format, this specifies attributes
+          to be placed inside the table tag.  This
           could for example be cellpadding or
           bgcolor. Note that you probably don't want
           to specify border here, as that is already
@@ -2152,6 +2160,13 @@ lo_import 152801
           value is given,
           the table attributes are unset.
           
+          
+          In latex-longtable format, this controls
+          the proportional width of each column containing a left-aligned
+          data type.  It is specified as a space-separated list of values,
+          e.g. '0.2 0.2 0.6'.  Unspecified output columns
+          use the last specified value.
+          
           
           
 
index 59f8b035511fd74f165b23859ce2fe7f00a6e654..740884ff3d8ec10acf80778b1eb3d33bf4928b9a 100644 (file)
@@ -2164,6 +2164,9 @@ _align2string(enum printFormat in)
        case PRINT_LATEX:
            return "latex";
            break;
+       case PRINT_LATEX_LONGTABLE:
+           return "latex-longtable";
+           break;
        case PRINT_TROFF_MS:
            return "troff-ms";
            break;
@@ -2197,6 +2200,8 @@ 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("latex-longtable", value, vallen) == 0)
+           popt->topt.format = PRINT_LATEX_LONGTABLE;
        else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
            popt->topt.format = PRINT_TROFF_MS;
        else
index 466c255978ca3b99eb3e0b190642740d3a1c311b..821058d4652ff8c04df513fceac3528724aea52f 100644 (file)
@@ -1612,8 +1612,8 @@ print_latex_text(const printTableContent *cont, FILE *fout)
    if (cancel_pressed)
        return;
 
-   if (opt_border > 2)
-       opt_border = 2;
+   if (opt_border > 3)
+       opt_border = 3;
 
    if (cont->opt->start_table)
    {
@@ -1628,7 +1628,7 @@ print_latex_text(const printTableContent *cont, FILE *fout)
        /* begin environment and set alignments and borders */
        fputs("\\begin{tabular}{", fout);
 
-       if (opt_border == 2)
+       if (opt_border >= 2)
            fputs("| ", fout);
        for (i = 0; i < cont->ncolumns; i++)
        {
@@ -1636,12 +1636,12 @@ print_latex_text(const printTableContent *cont, FILE *fout)
            if (opt_border != 0 && i < cont->ncolumns - 1)
                fputs(" | ", fout);
        }
-       if (opt_border == 2)
+       if (opt_border >= 2)
            fputs(" |", fout);
 
        fputs("}\n", fout);
 
-       if (!opt_tuples_only && opt_border == 2)
+       if (!opt_tuples_only && opt_border >= 2)
            fputs("\\hline\n", fout);
 
        /* print headers */
@@ -1668,6 +1668,8 @@ print_latex_text(const printTableContent *cont, FILE *fout)
        if ((i + 1) % cont->ncolumns == 0)
        {
            fputs(" \\\\\n", fout);
+           if (opt_border == 3)
+               fputs("\\hline\n", fout);
            if (cancel_pressed)
                break;
        }
@@ -1679,7 +1681,7 @@ print_latex_text(const printTableContent *cont, FILE *fout)
    {
        printTableFooter *footers = footers_with_default(cont);
 
-       if (opt_border == 2)
+       if (opt_border >= 2)
            fputs("\\hline\n", fout);
 
        fputs("\\end{tabular}\n\n\\noindent ", fout);
@@ -1701,6 +1703,162 @@ print_latex_text(const printTableContent *cont, FILE *fout)
 }
 
 
+static void
+print_latex_text_longtable(const printTableContent *cont, FILE *fout)
+{
+   bool        opt_tuples_only = cont->opt->tuples_only;
+   unsigned short opt_border = cont->opt->border;
+   unsigned int i;
+   const char *opt_table_attr = cont->opt->tableAttr;
+   const char *next_opt_table_attr_char = opt_table_attr;
+   const char *last_opt_table_attr_char = NULL;
+   const char *const * ptr;
+
+   if (cancel_pressed)
+       return;
+
+   if (opt_border > 3)
+       opt_border = 3;
+
+   if (cont->opt->start_table)
+   {
+       /* begin environment and set alignments and borders */
+       fputs("\\begin{longtable}{", fout);
+
+       if (opt_border >= 2)
+           fputs("| ", fout);
+
+       for (i = 0; i < cont->ncolumns; i++)
+       {
+           /* longtable supports either a width (p) or an alignment (l/r) */
+           /* Are we left-justified and was a proportional width specified? */
+           if (*(cont->aligns + i) == 'l' && opt_table_attr)
+           {
+#define LONGTABLE_WHITESPACE   " \t\n"
+
+               /* advance over whitespace */
+               next_opt_table_attr_char += strspn(next_opt_table_attr_char,
+                                                  LONGTABLE_WHITESPACE);
+               /* We have a value? */
+               if (next_opt_table_attr_char[0] != '\0')
+               {
+                   fputs("p{", fout);
+                   fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char,
+                          LONGTABLE_WHITESPACE), 1, fout);
+                   last_opt_table_attr_char = next_opt_table_attr_char;
+                   next_opt_table_attr_char += strcspn(next_opt_table_attr_char,
+                                                       LONGTABLE_WHITESPACE);
+                   fputs("\\textwidth}", fout);
+               }
+               /* use previous value */
+               else if (last_opt_table_attr_char != NULL)
+               {
+                   fputs("p{", fout);
+                   fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char,
+                          LONGTABLE_WHITESPACE), 1, fout);
+                   fputs("\\textwidth}", fout);
+               }
+               else
+                   fputc('l', fout);
+           }
+           else
+               fputc(*(cont->aligns + i), fout);
+
+           if (opt_border != 0 && i < cont->ncolumns - 1)
+               fputs(" | ", fout);
+       }
+
+       if (opt_border >= 2)
+           fputs(" |", fout);
+
+       fputs("}\n", fout);
+
+       /* print headers */
+       if (!opt_tuples_only)
+       {
+           /* firsthead */
+           if (opt_border >= 2)
+               fputs("\\toprule\n", fout);
+           for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
+           {
+               if (i != 0)
+                   fputs(" & ", fout);
+               fputs("\\small\\textbf{\\textit{", fout);
+               latex_escaped_print(*ptr, fout);
+               fputs("}}", fout);
+           }
+           fputs(" \\\\\n", fout);
+           fputs("\\midrule\n\\endfirsthead\n", fout);
+
+           /* secondary heads */
+           if (opt_border >= 2)
+               fputs("\\toprule\n", fout);
+           for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
+           {
+               if (i != 0)
+                   fputs(" & ", fout);
+               fputs("\\small\\textbf{\\textit{", fout);
+               latex_escaped_print(*ptr, fout);
+               fputs("}}", fout);
+           }
+           fputs(" \\\\\n", fout);
+           /* If the line under the row already appeared, don't do another */
+           if (opt_border != 3)
+               fputs("\\midrule\n", fout);
+           fputs("\\endhead\n", fout);
+
+           /* table name, caption? */
+           if (!opt_tuples_only && cont->title)
+           {
+               /* Don't output if we are printing a line under each row */
+               if (opt_border == 2)
+                   fputs("\\bottomrule\n", fout);
+               fputs("\\caption[", fout);
+               latex_escaped_print(cont->title, fout);
+               fputs(" (Continued)]{", fout);
+               latex_escaped_print(cont->title, fout);
+               fputs("}\n\\endfoot\n", fout);
+               if (opt_border == 2)
+                   fputs("\\bottomrule\n", fout);
+               fputs("\\caption[", fout);
+               latex_escaped_print(cont->title, fout);
+               fputs("]{", fout);
+               latex_escaped_print(cont->title, fout);
+               fputs("}\n\\endlastfoot\n", fout);
+           }
+           /* output bottom table line? */
+           else if (opt_border >= 2)
+           {
+               fputs("\\bottomrule\n\\endfoot\n", fout);
+               fputs("\\bottomrule\n\\endlastfoot\n", fout);
+           }
+       }
+   }
+
+   /* print cells */
+   for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+   {
+       /* Add a line under each row? */
+       if (i != 0 && i % cont->ncolumns != 0)
+           fputs("\n&\n", fout);
+       fputs("\\raggedright{", fout);
+       latex_escaped_print(*ptr, fout);
+       fputc('}', fout);
+       if ((i + 1) % cont->ncolumns == 0)
+       {
+           fputs(" \\tabularnewline\n", fout);
+           if (opt_border == 3)
+               fputs(" \\hline\n", fout);
+       }
+       if (cancel_pressed)
+           break;
+   }
+
+   if (cont->opt->stop_table)
+       fputs("\\end{longtable}\n", fout);
+}
+
+
 static void
 print_latex_vertical(const printTableContent *cont, FILE *fout)
 {
@@ -2394,6 +2552,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
            else
                print_latex_text(cont, fout);
            break;
+       case PRINT_LATEX_LONGTABLE:
+           if (cont->opt->expanded == 1)
+               print_latex_vertical(cont, fout);
+           else
+               print_latex_text_longtable(cont, fout);
+           break;
        case PRINT_TROFF_MS:
            if (cont->opt->expanded == 1)
                print_troff_ms_vertical(cont, fout);
index 63ba4a5d08a6f8661357f34ce64231ee962fa22d..9cfa3b6a4171a160e188b56012715bf65893b58a 100644 (file)
@@ -19,6 +19,7 @@ enum printFormat
    PRINT_WRAPPED,
    PRINT_HTML,
    PRINT_LATEX,
+   PRINT_LATEX_LONGTABLE,
    PRINT_TROFF_MS
    /* add your favourite output format here ... */
 };