From 80a956c0d24e53a1b44619774b099364a585cdd0 Mon Sep 17 00:00:00 2001 From: Roger Leigh Date: Sat, 24 Oct 2009 18:11:01 +0100 Subject: [PATCH] psql: Clean up line wrapping for Unicode display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, there were two different methods for displaying wrapping: 1) Columns headers used a "+" symbol in the left-hand border when the column heading contained newlines. 2) Data lines used either a ":" or ";" symbol to represent wrapped and new lines, and " " to represent empty lines. These symbols replaced the "|" immediately to the left of the column. This patch unifies both of these, by making (1)-like formatting the behaviour for all new lines in both column headers and data. It indicates wrapping by using "." symbols in the border for continuations. When using Unicode, these are replaced by "↵" (carriage return) for newlines and "…" (ellipses) for continuations. --- src/bin/psql/print.c | 120 +++++++++++++++++++++++++++++--------------------- src/bin/psql/print.h | 15 +++++- 2 files changed, 81 insertions(+), 54 deletions(-) diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 026e043..212e9a1 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -54,9 +54,10 @@ const printTextFormat pg_asciiformat = { "-", "+", "+", "+" }, { "", "|", "|", "|" } }, - ":", - ";", - " " + " ", + "+", + ".", + "." }; const printTextFormat pg_utf8format = @@ -72,12 +73,13 @@ const printTextFormat pg_utf8format = /* N/A, │, │, │ */ { "", "\342\224\202", "\342\224\202", "\342\224\202" } }, - /* ╎ */ - "\342\225\216", - /* ┊ */ - "\342\224\212", - /* ╷ */ - "\342\225\267" + " ", + /* ↵ */ + "\342\206\265", + /* … */ + "\342\200\246", + /* … */ + "\342\200\246" }; @@ -575,7 +577,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) /* adjust the total display width based on border style */ if (opt_border == 0) - width_total = col_count - 1; + width_total = col_count; else if (opt_border == 1) width_total = col_count * 3 - 1; else @@ -770,16 +772,16 @@ print_aligned_text(const printTableContent *cont, FILE *fout) while (more_col_wrapping) { if (opt_border == 2) - fprintf(fout, "%s%c", dformat->leftvrule, - curr_nl_line ? '+' : ' '); - else if (opt_border == 1) - fputc(curr_nl_line ? '+' : ' ', fout); + fputs(dformat->leftvrule, fout); for (i = 0; i < cont->ncolumns; i++) { struct lineptr *this_line = col_lineptrs[i] + curr_nl_line; unsigned int nbspace; + if (opt_border != 0) + fputs(curr_nl_line ? format->cont_left : " ", fout); + if (!header_done[i]) { nbspace = width_wrap[i] - this_line->width; @@ -796,21 +798,16 @@ print_aligned_text(const printTableContent *cont, FILE *fout) } else fprintf(fout, "%*s", width_wrap[i], ""); - if (i < col_count - 1) - { - if (opt_border == 0) - fputc(curr_nl_line ? '+' : ' ', fout); - else - fprintf(fout, " %s%c", dformat->midvrule, - curr_nl_line ? '+' : ' '); - } + + fputs(!header_done[i] ? format->cont_right : " ", fout); + + if (opt_border != 0 && i < col_count - 1) + fputs(dformat->midvrule, fout); } curr_nl_line++; if (opt_border == 2) - fprintf(fout, " %s", dformat->rightvrule); - else if (opt_border == 1) - fputc(' ', fout); + fputs(dformat->rightvrule, fout); fputc('\n', fout); } @@ -861,18 +858,39 @@ print_aligned_text(const printTableContent *cont, FILE *fout) /* left border */ if (opt_border == 2) - fprintf(fout, "%s ", dformat->leftvrule); - else if (opt_border == 1) - fputc(' ', fout); + fputs(dformat->leftvrule, fout); /* for each column */ for (j = 0; j < col_count; j++) { /* We have a valid array element, so index it */ struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]]; - int bytes_to_output; - int chars_to_output = width_wrap[j]; + int bytes_to_output; + int chars_to_output = width_wrap[j]; bool finalspaces = (opt_border == 2 || j < col_count - 1); + printTextLineWrap wrapping = PRINT_LINE_WRAP_NONE; + + /* Determine if column is wrapped or a newline */ + if (col_lineptrs[j][curr_nl_line[j]].ptr == NULL) + wrapping = PRINT_LINE_WRAP_NONE; + else + { + if (bytes_output[j] != 0) + wrapping |= PRINT_LINE_WRAP_WRAP; + else if (curr_nl_line[j] != 0) + wrapping |= PRINT_LINE_WRAP_CONT; + } + + /* Print left-hand wrap or newline mark */ + if (opt_border != 0) + { + if (wrapping & PRINT_LINE_WRAP_WRAP) + fputs(format->wrap_left, fout); + else if (wrapping & PRINT_LINE_WRAP_CONT) + fputs(format->cont_left, fout); + else + fputc(' ', fout); + } if (!this_line->ptr) { @@ -908,7 +926,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) /* spaces second */ fprintf(fout, "%.*s", bytes_to_output, this_line->ptr + bytes_output[j]); - if (finalspaces) + if (finalspaces || col_lineptrs[j][curr_nl_line[j]].ptr != NULL) fprintf(fout, "%*s", width_wrap[j] - chars_to_output, ""); } @@ -927,29 +945,31 @@ print_aligned_text(const printTableContent *cont, FILE *fout) } } - /* print a divider, if not the last column */ - if (j < col_count - 1) + /* Determine if next line for this column is wrapped or a newline */ + if (col_lineptrs[j][curr_nl_line[j]].ptr == NULL) + wrapping = PRINT_LINE_WRAP_NONE; + else { - if (opt_border == 0) - fputc(' ', fout); - /* Next value is beyond past newlines? */ - else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL) - fprintf(fout, " %s ", format->midvrule_blank); - /* In wrapping of value? */ - else if (bytes_output[j + 1] != 0) - fprintf(fout, " %s ", format->midvrule_wrap); - /* After first newline value */ - else if (curr_nl_line[j + 1] != 0) - fprintf(fout, " %s ", format->midvrule_cont); - /* Ordinary line */ - else - fprintf(fout, " %s ", dformat->midvrule); + if (bytes_output[j] != 0) + wrapping |= PRINT_LINE_WRAP_WRAP; + else if (curr_nl_line[j] != 0) + wrapping |= PRINT_LINE_WRAP_CONT; } + + /* Print right-hand wrap or newline mark */ + if (wrapping & PRINT_LINE_WRAP_WRAP) + fputs(format->wrap_right, fout); + else if (wrapping & PRINT_LINE_WRAP_CONT) + fputs(format->cont_right, fout); + else if (!(opt_border == 0 && j == col_count - 1)) + fputc(' ', fout); + if (opt_border != 0 && j < col_count - 1) + fputs(dformat->midvrule, fout); } /* end-of-row border */ if (opt_border == 2) - fprintf(fout, " %s", dformat->rightvrule); + fputs(dformat->rightvrule, fout); fputc('\n', fout); } while (more_lines); @@ -1196,9 +1216,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) fprintf(fout, "%*s", hwidth, ""); if (opt_border > 0) - fprintf(fout, " %s ", - (line_count == 0) ? - format->midvrule_cont : dformat->midvrule); + fprintf(fout, " %s ", dformat->midvrule); else fputc(' ', fout); diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index 056aaa6..087d972 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -41,14 +41,23 @@ typedef enum printTextRule PRINT_RULE_DATA /* data line (hrule is unused here) */ } printTextRule; +typedef enum printTextLineWrap +{ + /* Types of line continuation and wrapping */ + PRINT_LINE_WRAP_NONE = 0, /* No wrapping */ + PRINT_LINE_WRAP_WRAP = 1 << 0, /* Line is wrapped */ + PRINT_LINE_WRAP_CONT = 1 << 1, /* Continuation after newline */ +} printTextLineWrap; + typedef struct printTextFormat { /* A complete line style */ const char *name; /* for display purposes */ printTextLineFormat lrule[4]; /* indexed by enum printTextRule */ - const char *midvrule_cont; /* vertical line for continue after newline */ - const char *midvrule_wrap; /* vertical line for wrapped data */ - const char *midvrule_blank; /* vertical line for blank data */ + const char *cont_left; /* continue after newline */ + const char *cont_right;/* continue after newline */ + const char *wrap_left; /* wrapped data */ + const char *wrap_right; /* wrapped data */ } printTextFormat; typedef struct printTableOpt -- 1.6.5