On Fri, Oct 16, 2009 at 01:38:15PM +0300, Peter Eisentraut wrote:
> I like the new Unicode tables, but the marking of continuation lines
> looks pretty horrible:
> 
>                              List of databases
>      Name      │ Owner │ Encoding │ Collation │ Ctype │ Access
> privileges
> ───────────────┼───────┼──────────┼───────────┼───────┼───────────────────
>  pl_regression │ peter │ LATIN2   │ cs_CZ     │ cs_CZ │
>  postgres      │ peter │ LATIN2   │ cs_CZ     │ cs_CZ │
>  template0     │ peter │ LATIN2   │ cs_CZ     │ cs_CZ │ =c/peter
>                ╷       ╷          ╷           ╷       ╎ peter=CTc/peter
>  template1     │ peter │ LATIN2   │ cs_CZ     │ cs_CZ │ =c/peter
>                ╷       ╷          ╷           ╷       ╎ peter=CTc/peter
> (4 rows)
> 
> This looks more like a rendering mistake than something sensible, and
> also it doesn't actually help the viewer to tell what lines are
> continued, which was the original purpose.

I've worked on a solution to this, and the preliminary patch for this
is attached.  Note there are additional comments in the patch text.

This patch does break backward compatibility with older psql versions,
by using symbols in the column border to mark newlines and wrapped
lines rather than putting ':' and ';' and ' ' symbols in the vertical
table lines.  This makes things somewhat more consistent and readable
but at the expense of not perfectly preserving output.  The ASCII
rules are a little more compatible than the Unicode rules, but both
do break things a little.  If the data lines do not contain either
newlines or wrapped text, then the output will remain unchanged.

Any feedback would be appreciated.


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.
From 245c6cabe7d74afef976149fd675bd99d711cade Mon Sep 17 00:00:00 2001
From: Roger Leigh <rle...@debian.org>
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 lies 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) 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 "↩" and "↪" (curly arrows) for continuations.

In the special case of a border size of zero, only the right-hand
border symbols are drawn, since there is no space for any other
output.  The right-most column will not display any symbols for
backward compatibility, but this can be adjusted (I think it would
make the display somewhat more consistent).
---
 src/bin/psql/print.c |  114 ++++++++++++++++++++++++++++---------------------
 src/bin/psql/print.h |   17 ++++++-
 2 files changed, 79 insertions(+), 52 deletions(-)

diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 026e043..f20eab1 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\206\252",
+	/* ↩ */
+	"\342\206\251"
 };
 
 
@@ -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 column wrapping */
+				/* In wrapping of value? */
+				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_START;
+					else if (curr_nl_line[j] != 0)
+						wrapping |= PRINT_LINE_CONT_START;
+				}
+
+				if (opt_border != 0)
+				{
+					if (wrapping & PRINT_LINE_WRAP_START)
+						fputs(format->wrap_left, fout);
+					else if (wrapping & PRINT_LINE_CONT_START)
+						fputs(format->cont_left, fout);
+					else
+						fputc(' ', fout);
+				}
 
 				if (!this_line->ptr)
 				{
@@ -927,29 +945,29 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 					}
 				}
 
-				/* print a divider, if not the last column */
-				if (j < col_count - 1)
+				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_END;
+					else if (curr_nl_line[j] != 0)
+						wrapping |= PRINT_LINE_CONT_END;
 				}
+
+				if (wrapping & PRINT_LINE_WRAP_END)
+					fputs(format->wrap_right, fout);
+				else if (wrapping & PRINT_LINE_CONT_END)
+					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 +1214,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..4b31302 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -41,14 +41,25 @@ 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  = 0x00, /* No wrapping */
+  PRINT_LINE_WRAP_START = 1 << 0, /* Line precedes wrap */
+  PRINT_LINE_WRAP_END   = 1 << 1, /* Line follows wrap */
+  PRINT_LINE_CONT_START = 1 << 2, /* Line contains newline */
+  PRINT_LINE_CONT_END   = 1 << 3  /* Line is preceded by 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

Attachment: signature.asc
Description: Digital signature

Reply via email to