Thread: [PATCH 1/6] psql: Abstract table formatting characters used for different line types.
[PATCH 1/6] psql: Abstract table formatting characters used for different line types.
From
Roger Leigh
Date:
printTextLineFormat describes the characters used to draw vertical lines across a horizontal rule at the left side, middle and right hand side. These are included in the formatting for an entire table (printTextFormat). The printTextRule enum is used as an offset into the printTextFormat line rules (lrule), allowing specification of line styles for the top, middle and bottom horizontal lines in a table. The other printTextFormat members, hrule and vrule define the formatting needed to draw horizontal and vertical rules. Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.h | 21 +++++++++++++++++++++1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index 55122d7..ffca5d4 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -95,6 +95,27 @@ typedef struct printQueryOpt * gettext on col i */} printQueryOpt; +typedef struct printTextLineFormat +{ + const char *leftvrule; + const char *midvrule; + const char *rightvrule; +} printTextLineFormat; + +typedef struct printTextFormat +{ + printTextLineFormat lrule[3]; + const char *hrule; + const char *vrule; +} printTextFormat; + +typedef enum printTextRule +{ + PRINT_RULE_TOP, + PRINT_RULE_MIDDLE, + PRINT_RULE_BOTTOM +} printTextRule; +extern FILE *PageOutput(int lines, unsigned short int pager);extern void ClosePager(FILE *pagerpipe); -- 1.6.3.3
print_aligned_text and print_aligned_vertical, and their helper fuctions pass the table formatting and (where applicable) line style information to allow correct printing of table lines. Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.c | 23 ++++++++++++++---------1 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 6f5dcd4..641fd63 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -387,7 +387,9 @@ static const struct printTextFormat utf8format =/* draw "line" */static void_print_horizontal_line(constunsigned int ncolumns, const unsigned int *widths, - unsigned short border, FILE *fout) + unsigned short border, printTextRule pos, + const printTextFormat *format, + FILE *fout){ unsigned int i, j; @@ -424,7 +426,8 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, * Print pretty boxesaround cells. */static void -print_aligned_text(const printTableContent *cont, FILE *fout) +print_aligned_text(const printTableContent *cont, const printTextFormat *format, + FILE *fout){ bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale = cont->opt->numericLocale; @@ -736,7 +739,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) int curr_nl_line; if (opt_border == 2) - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_TOP, format, fout); for(i = 0; i < col_count; i++) pg_wcsformat((unsigned char *) cont->headers[i], @@ -792,7 +795,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) fputc('\n', fout); } - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_MIDDLE, format, fout); } } @@ -935,7 +938,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) if (cont->opt->stop_table) { if (opt_border == 2 && !cancel_pressed) - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_BOTTOM, format, fout); /* printfooters */ if (cont->footers && !opt_tuples_only && !cancel_pressed) @@ -970,7 +973,9 @@ print_aligned_text(const printTableContent *cont, FILE *fout)static void -print_aligned_vertical(const printTableContent *cont, FILE *fout) +print_aligned_vertical(const printTableContent *cont, + const printTextFormat *format, + FILE *fout){ bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale =cont->opt->numericLocale; @@ -2258,7 +2263,7 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog) /* print the stuff */ if (flog) - print_aligned_text(cont, flog); + print_aligned_text(cont, text_format, flog); switch (cont->opt->format) { @@ -2271,9 +2276,9 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog) case PRINT_ALIGNED: case PRINT_WRAPPED: if (cont->opt->expanded) - print_aligned_vertical(cont, fout); + print_aligned_vertical(cont, text_format, fout); else - print_aligned_text(cont, fout); + print_aligned_text(cont, text_format, fout); break; case PRINT_HTML: if (cont->opt->expanded) -- 1.6.3.3
Convert print_aligned_vertical, and its helper function, to use table formatting in place of hardcoded ASCII characters. Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.c | 141 +++++++++++++++++++++++++++++++-------------------1 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 84f6bdc..e4e9f01 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -995,6 +995,68 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, ClosePager(fout);} +static inline void +print_aligned_vertical_line(const printTableContent *cont, + unsigned long record, + unsigned int hwidth, + unsigned int dwidth, + printTextRule pos, + const printTextFormat *format, + FILE *fout) +{ + unsigned short opt_border = cont->opt->border; + unsigned int i; + int reclen = 0; + const printTextLineFormat *lformat = &format->lrule[pos]; + + if (opt_border == 2) + { + fputs(lformat->leftvrule, fout); + fputs(format->hrule, fout); + } + else + fputs(format->hrule, fout); + + if (record) + { + if (opt_border == 0) + reclen = fprintf(fout, "* Record %lu", record); + else + reclen = fprintf(fout, "[ RECORD %lu ]", record); + } + if (opt_border != 2) + reclen++; + if (reclen < 0) + reclen = 0; + for (i = reclen; i < hwidth; i++) + fputs(opt_border > 0 ? format->hrule : " ", fout); + reclen -= hwidth; + + if (opt_border > 0) + { + if (--reclen <= 0) + fputs(format->hrule, fout); + if (--reclen <= 0) + fputs(lformat->midvrule, fout); + if (--reclen <= 0) + fputs(format->hrule, fout); + } + else + { + if (reclen-- > 0) + fputs(" ", fout); + } + if (reclen < 0) + reclen = 0; + for (i = reclen; i < dwidth; i++) + fputs(opt_border > 0 ? format->hrule : " ", fout); + if (opt_border == 2) + { + fputs(format->hrule, fout); + fputs(lformat->rightvrule, fout); + } + fputc('\n', fout); +}static voidprint_aligned_vertical(const printTableContent *cont, @@ -1014,7 +1076,6 @@ print_aligned_vertical(const printTableContent *cont, dheight = 1, hformatsize= 0, dformatsize = 0; - char *divider; struct lineptr *hlineptr, *dlineptr; @@ -1082,21 +1143,6 @@ print_aligned_vertical(const printTableContent *cont, dlineptr->ptr = pg_local_malloc(dformatsize); hlineptr->ptr = pg_local_malloc(hformatsize); - /* make horizontal border */ - divider = pg_local_malloc(hwidth + dwidth + 10); - divider[0] = '\0'; - if (opt_border == 2) - strcat(divider, "+-"); - for (i = 0; i < hwidth; i++) - strcat(divider, opt_border > 0 ? "-" : " "); - if (opt_border > 0) - strcat(divider, "-+-"); - else - strcat(divider, " "); - for (i = 0; i < dwidth; i++) - strcat(divider, opt_border > 0 ? "-" : " "); - if (opt_border == 2) - strcat(divider, "-+"); if (cont->opt->start_table) { @@ -1108,40 +1154,25 @@ print_aligned_vertical(const printTableContent *cont, /* print records */ for (i = 0, ptr =cont->cells; *ptr; i++, ptr++) { - int line_count, - dcomplete, - hcomplete; + int line_count, + dcomplete, + hcomplete; + printTextRule pos = PRINT_RULE_MIDDLE; + if (i == 0) + pos = PRINT_RULE_TOP; + else if (!(*(ptr+1))) + pos = PRINT_RULE_BOTTOM; + + if (cancel_pressed) + break; if (i % cont->ncolumns == 0) { - if (cancel_pressed) - break; - if (!opt_tuples_only) - { - char record_str[64]; - size_t record_str_len; - - if (opt_border == 0) - snprintf(record_str, 64, "* Record %lu", record++); - else - snprintf(record_str, 64, "[ RECORD %lu ]", record++); - record_str_len = strlen(record_str); - - if (record_str_len + opt_border > strlen(divider)) - fprintf(fout, "%.*s%s\n", opt_border, divider, record_str); - else - { - char *div_copy = pg_strdup(divider); - - strncpy(div_copy + opt_border, record_str, record_str_len); - fprintf(fout, "%s\n", div_copy); - free(div_copy); - } - } + if (!opt_tuples_only) + print_aligned_vertical_line(cont, record++, hwidth, dwidth, pos, format, fout); else if (i !=0 || !cont->opt->start_table || opt_border == 2) - fprintf(fout, "%s\n", divider); + print_aligned_vertical_line(cont, 0, hwidth, dwidth, pos, format, fout); } - /* Format the header */ pg_wcsformat((unsigned char *) cont->headers[i % cont->ncolumns], strlen(cont->headers[i % cont->ncolumns]), @@ -1155,7 +1186,10 @@ print_aligned_vertical(const printTableContent *cont, while (!dcomplete || !hcomplete) { if (opt_border == 2) - fputs("| ", fout); + { + fputs(format->vrule, fout); + fputc(' ', fout); + } if (!hcomplete) { fprintf(fout, "%-s%*s", hlineptr[line_count].ptr, @@ -1168,7 +1202,7 @@ print_aligned_vertical(const printTableContent *cont, fprintf(fout, "%*s", hwidth, ""); if (opt_border > 0) - fprintf(fout, " %c ", (line_count == 0) ? '|' : ':'); + fprintf(fout, " %s ", (line_count == 0) ? format->vrule : ":"); else fputs(" ",fout); @@ -1181,8 +1215,8 @@ print_aligned_vertical(const printTableContent *cont, if (opt_border < 2) fprintf(fout, "%s\n", my_cell); else - fprintf(fout, "%-s%*s |\n", my_cell, - (int) (dwidth - strlen(my_cell)), ""); + fprintf(fout, "%-s%*s %s\n", my_cell, + (int) (dwidth - strlen(my_cell)), "", format->vrule); free(my_cell); } else @@ -1190,8 +1224,8 @@ print_aligned_vertical(const printTableContent *cont, if (opt_border < 2) fprintf(fout, "%s\n", dlineptr[line_count].ptr); else - fprintf(fout, "%-s%*s |\n", dlineptr[line_count].ptr, - dwidth - dlineptr[line_count].width, ""); + fprintf(fout, "%-s%*s %s\n", dlineptr[line_count].ptr, + dwidth - dlineptr[line_count].width, "", format->vrule); } if (!dlineptr[line_count + 1].ptr) @@ -1202,7 +1236,7 @@ print_aligned_vertical(const printTableContent *cont, if (opt_border < 2) fputc('\n', fout); else - fprintf(fout, "%*s |\n", dwidth, ""); + fprintf(fout, "%*s %s\n", dwidth, "", format->vrule); } line_count++; } @@ -1211,7 +1245,7 @@ print_aligned_vertical(const printTableContent *cont, if (cont->opt->stop_table) { if(opt_border == 2 && !cancel_pressed) - fprintf(fout, "%s\n", divider); + print_aligned_vertical_line(cont, 0, hwidth, dwidth, PRINT_RULE_BOTTOM, format, fout); /* print footers*/ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) @@ -1227,7 +1261,6 @@ print_aligned_vertical(const printTableContent *cont, fputc('\n', fout); } - free(divider); free(hlineptr->ptr); free(dlineptr->ptr); free(hlineptr); -- 1.6.3.3
Convert print_aligned_text, and its helper function, to use table formatting in place of hardcoded ASCII characters. Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.c | 50 +++++++++++++++++++++++++++++++++++++-------------1 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 641fd63..84f6bdc 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -394,29 +394,41 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, unsigned int i, j; + const printTextLineFormat *lformat = &format->lrule[pos]; + if (border == 1) - fputc('-', fout); + fputs(format->hrule, fout); else if (border == 2) - fputs("+-", fout); + { + fputs(lformat->leftvrule, fout); + fputs(format->hrule, fout); + } for (i = 0; i < ncolumns; i++) { for (j = 0; j < widths[i]; j++) - fputc('-', fout); + fputs(format->hrule, fout); if (i < ncolumns - 1) { if (border == 0) fputc(' ', fout); else - fputs("-+-", fout); + { + fputs(format->hrule, fout); + fputs(lformat->midvrule, fout); + fputs(format->hrule, fout); + } } } if (border == 2) - fputs("-+", fout); + { + fputs(format->hrule, fout); + fputs(lformat->rightvrule, fout); + } else if (border == 1) - fputc('-', fout); + fputs(format->hrule, fout); fputc('\n', fout);} @@ -752,7 +764,7 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, while (more_col_wrapping) { if (opt_border == 2) - fprintf(fout, "|%c", curr_nl_line ? '+' : ' '); + fprintf(fout, "%s%c", format->vrule, curr_nl_line ? '+' : ' '); else if (opt_border ==1) fputc(curr_nl_line ? '+' : ' ', fout); @@ -783,13 +795,16 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, if (opt_border == 0) fputc(curr_nl_line ? '+' : ' ', fout); else - fprintf(fout, " |%c", curr_nl_line ? '+' : ' '); + fprintf(fout, " %s%c", format->vrule, curr_nl_line ? '+' : ' '); } } curr_nl_line++; if (opt_border == 2) - fputs(" |", fout); + { + fputc(' ', fout); + fputs(format->vrule, fout); + } else if (opt_border == 1) fputc(' ', fout); fputc('\n',fout); @@ -841,7 +856,10 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, /* leftborder */ if (opt_border == 2) - fputs("| ", fout); + { + fputs(format->vrule, fout); + fputc(' ', fout); + } else if (opt_border == 1) fputc(' ', fout); @@ -922,14 +940,20 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, else if (curr_nl_line[j + 1] != 0) fputs(" : ", fout); else + { /* Ordinary line */ - fputs(" | ", fout); + fputc(' ', fout); + fputs(format->vrule, fout); + fputc(' ', fout); + } } } /* end-of-row border */ - if (opt_border == 2) - fputs(" |", fout); + if (opt_border == 2) { + fputc(' ', fout); + fputs(format->vrule, fout); + } fputc('\n', fout); } while (more_lines); -- 1.6.3.3
Default to using the ASCII table. However, if a UTF-8 locale codeset is in use, switch to the UTF-8 table. Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.c | 11 ++++++++++-1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 9dec77d..6f5dcd4 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -21,6 +21,9 @@#endif#include <locale.h> +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif#include "catalog/pg_type.h"#include "pqsignal.h" @@ -2232,7 +2235,13 @@ IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout,voidprintTable(constprintTableContent *cont, FILE *fout, FILE *flog){ - bool is_pager = false; + bool is_pager = false; + const printTextFormat *text_format = &asciiformat; + +#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) + if (!strcmp(nl_langinfo(CODESET), "UTF-8")) + text_format = &utf8format; +#endif if (cancel_pressed) return; -- 1.6.3.3
Signed-off-by: Roger Leigh <rleigh@debian.org> ---src/bin/psql/print.c | 24 ++++++++++++++++++++++++1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 7505cd4..9dec77d 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -356,6 +356,30 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)/* Aligned text *//********************/ +static const printTextFormat asciiformat = +{ + { + { "+", "+", "+" }, + { "+", "+", "+" }, + { "+", "+", "+" } + }, + "-", + "|" +}; + +static const struct printTextFormat utf8format = +{ + { + /* ┌, ┬, ┐ */ + { "\342\224\214", "\342\224\254", "\342\224\220" }, + /* ├, ┼, ┤ */ + { "\342\224\234", "\342\224\274", "\342\224\244" }, + /* └, ┴, ┘ */ + { "\342\224\224", "\342\224\264", "\342\224\230" } + }, + "\342\224\200", /* ─ */ + "\342\224\202" /* │ */ +};/* draw "line" */static void -- 1.6.3.3
On Sun, Aug 23, 2009 at 11:47:02AM -0400, Alvaro Herrera wrote: > Roger Leigh wrote: > > Convert print_aligned_text, and its helper function, to use > > table formatting in place of hardcoded ASCII characters. > > > @@ -841,7 +856,10 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, > > > > /* left border */ > > if (opt_border == 2) > > - fputs("| ", fout); > > + { > > + fputs(format->vrule, fout); > > + fputc(' ', fout); > > + } > > else if (opt_border == 1) > > fputc(' ', fout); > > Wouldn't it be better to do a single fprintf call here instead of > fputc + fputs? It's certainly possible to change it; the above might be slightly more efficient than a call to fprintf since you skip parsing the format string, but otherwise I have no real preference for one over the other. Regards, Roger -- .''`. Roger Leigh: :' : Debian GNU/Linux http://people.debian.org/~rleigh/`. `' Printing on GNU/Linux? http://gutenprint.sourceforge.net/ `- GPG Public Key: 0x25BFB848 Please GPG sign your mail.
Roger Leigh wrote: > Convert print_aligned_text, and its helper function, to use > table formatting in place of hardcoded ASCII characters. > @@ -841,7 +856,10 @@ print_aligned_text(const printTableContent *cont, const printTextFormat *format, > > /* left border */ > if (opt_border == 2) > - fputs("| ", fout); > + { > + fputs(format->vrule, fout); > + fputc(' ', fout); > + } > else if (opt_border == 1) > fputc(' ', fout); Wouldn't it be better to do a single fprintf call here instead of fputc + fputs? -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Roger Leigh wrote: > On Sun, Aug 23, 2009 at 11:47:02AM -0400, Alvaro Herrera wrote: > > Wouldn't it be better to do a single fprintf call here instead of > > fputc + fputs? > > It's certainly possible to change it; the above might be slightly more > efficient than a call to fprintf since you skip parsing the format > string, but otherwise I have no real preference for one over the > other. There are already other fprintf calls in the same function -- I wouldn't worry too much about some hypothetical performance gain. Let's keep things simple and readable. -- Alvaro Herrera http://www.CommandPrompt.com/ The PostgreSQL Company - Command Prompt, Inc.