From b14f81bc9a65993129e93052634e358b310b8554 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 17 Jan 2013 11:39:38 -0500 Subject: [PATCH] Add a latex-longtable output format to psql 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 | 31 ++++-- src/bin/psql/command.c | 5 + src/bin/psql/print.c | 176 +++++++++++++++++++++++++++++++-- src/bin/psql/print.h | 1 + 4 files changed, 199 insertions(+), 14 deletions(-) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index c41593c5e36..504a5164de9 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -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, aligned, wrapped, 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. + diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 59f8b035511..740884ff3d8 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -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 diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 466c255978c..821058d4652 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -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); diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index 63ba4a5d08a..9cfa3b6a417 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -19,6 +19,7 @@ enum printFormat PRINT_WRAPPED, PRINT_HTML, PRINT_LATEX, + PRINT_LATEX_LONGTABLE, PRINT_TROFF_MS /* add your favourite output format here ... */ };