]> granicus.if.org Git - postgresql/commitdiff
Add a latex-longtable output format to psql
authorBruce Momjian <bruce@momjian.us>
Thu, 17 Jan 2013 16:39:38 +0000 (11:39 -0500)
committerBruce Momjian <bruce@momjian.us>
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 <literal>border=...</literal> attribute; in the
           other formats only values 0 (no border), 1 (internal dividing lines),
           and 2 (table frame) make sense.
+          <literal>latex</literal> and <literal>latex-longtable</literal>
+          also support a <literal>border</literal> value of 3 which adds
+          a dividing line between each row.
           </para>
           </listitem>
           </varlistentry>
@@ -1979,7 +1982,9 @@ lo_import 152801
           Sets the output format to one of <literal>unaligned</literal>,
           <literal>aligned</literal>, <literal>wrapped</literal>,
           <literal>html</literal>,
-          <literal>latex</literal>, or <literal>troff-ms</literal>.
+          <literal>latex</literal> (uses <literal>tabular</literal>),
+          <literal>latex-longtable</literal>, or
+          <literal>troff-ms</literal>.
           Unique abbreviations are allowed.  (That would mean one letter
           is enough.)
           </para>
@@ -2005,12 +2010,16 @@ lo_import 152801
           </para>
 
           <para>
-          The <literal>html</>, <literal>latex</>, and <literal>troff-ms</>
+          The <literal>html</>, <literal>latex</>,
+          <literal>latex-longtable</literal>, and <literal>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 <acronym>HTML</acronym>, but in <application>LaTeX</application> you must
-          have a complete document wrapper.)
+          language. They are not complete documents! This might not be
+          necessary in <acronym>HTML</acronym>, but in
+          <application>LaTeX</application> you must have a complete
+          document wrapper.  <literal>latex-longtable</literal>
+          also requires the <application>LaTeX</application>
+          <literal>longtable</literal> and <literal>booktabs</> packages.
           </para>
           </listitem>
           </varlistentry>
@@ -2141,9 +2150,8 @@ lo_import 152801
           <term><literal>tableattr</literal> (or <literal>T</literal>)</term>
           <listitem>
           <para>
-          Specifies attributes to be placed inside the
-          <acronym>HTML</acronym> <sgmltag>table</sgmltag> tag in
-          <literal>html</> output format. This
+          In <acronym>HTML</acronym> format, this specifies attributes
+          to be placed inside the <sgmltag>table</sgmltag> tag.  This
           could for example be <literal>cellpadding</literal> or
           <literal>bgcolor</literal>. Note that you probably don't want
           to specify <literal>border</literal> here, as that is already
@@ -2152,6 +2160,13 @@ lo_import 152801
           <replaceable class="parameter">value</replaceable> is given,
           the table attributes are unset.
           </para>
+          <para>
+          In <literal>latex-longtable</literal> 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. <literal>'0.2 0.2 0.6'</>.  Unspecified output columns
+          use the last specified value.
+          </para>
           </listitem>
           </varlistentry>
 
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 ... */
 };