mirror of https://github.com/postgres/postgres
Add unicode_{column|header|border}_style to psql
With the unicode linestyle, this adds support to control if the column, header, or border style should be single or double line unicode characters. The default remains 'single'. In passing, clean up the border documentation and address some minor formatting/spelling issues. Pavel Stehule, with some additional changes by me.
This commit is contained in:
parent
82962838d4
commit
a2dabf0e1d
|
@ -1996,12 +1996,12 @@ lo_import 152801
|
|||
the number the more borders and lines the tables will have,
|
||||
but this depends on the particular format. In
|
||||
<acronym>HTML</acronym> format, this will translate directly
|
||||
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.
|
||||
into the <literal>border=...</literal> attribute; in
|
||||
<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.
|
||||
formats, a value of 3 will add a dividing line between each row; in
|
||||
the other formats only values 0 (no border), 1 (internal dividing
|
||||
lines), and 2 (table frame) make sense and values above 2 will be
|
||||
treated the same as <literal>border = 2</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -2306,6 +2306,36 @@ lo_import 152801
|
|||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>unicode_border_style</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the border drawing style for the unicode linestyle to one
|
||||
of <literal>single</literal> or <literal>double</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>unicode_column_style</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the column drawing style for the unicode linestyle to one
|
||||
of <literal>single</literal> or <literal>double</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>unicode_header_style</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the header drawing style for the unicode linestyle to one
|
||||
of <literal>single</literal> or <literal>double</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
|
|
|
@ -1054,6 +1054,9 @@ exec_command(const char *cmd,
|
|||
"footer", "format", "linestyle", "null",
|
||||
"numericlocale", "pager", "recordsep",
|
||||
"tableattr", "title", "tuples_only",
|
||||
"unicode_border_linestyle",
|
||||
"unicode_column_linestyle",
|
||||
"unicode_header_linestyle",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -2248,6 +2251,41 @@ _align2string(enum printFormat in)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse entered unicode linestyle. Returns true, when entered string is
|
||||
* known linestyle: single, double else returns false.
|
||||
*/
|
||||
static bool
|
||||
set_unicode_line_style(printQueryOpt *popt, const char *value, size_t vallen,
|
||||
unicode_linestyle *linestyle)
|
||||
{
|
||||
if (pg_strncasecmp("single", value, vallen) == 0)
|
||||
*linestyle = UNICODE_LINESTYLE_SINGLE;
|
||||
else if (pg_strncasecmp("double", value, vallen) == 0)
|
||||
*linestyle = UNICODE_LINESTYLE_DOUBLE;
|
||||
else
|
||||
return false;
|
||||
|
||||
/* input is ok, generate new unicode style */
|
||||
refresh_utf8format(&(popt->topt));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_unicode_linestyle2string(int linestyle)
|
||||
{
|
||||
switch (linestyle)
|
||||
{
|
||||
case UNICODE_LINESTYLE_SINGLE:
|
||||
return "single";
|
||||
break;
|
||||
case UNICODE_LINESTYLE_DOUBLE:
|
||||
return "double";
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bool
|
||||
do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
|
||||
|
@ -2305,6 +2343,45 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
|
|||
|
||||
}
|
||||
|
||||
/* set unicode border line style */
|
||||
else if (strcmp(param, "unicode_border_linestyle") == 0)
|
||||
{
|
||||
if (!value)
|
||||
;
|
||||
else if (!set_unicode_line_style(popt, value, vallen,
|
||||
&popt->topt.unicode_border_linestyle))
|
||||
{
|
||||
psql_error("\\pset: allowed unicode border linestyle are single, double\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* set unicode column line style */
|
||||
else if (strcmp(param, "unicode_column_linestyle") == 0)
|
||||
{
|
||||
if (!value)
|
||||
;
|
||||
else if (!set_unicode_line_style(popt, value, vallen,
|
||||
&popt->topt.unicode_column_linestyle))
|
||||
{
|
||||
psql_error("\\pset: allowed unicode column linestyle are single, double\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* set unicode header line style */
|
||||
else if (strcmp(param, "unicode_header_linestyle") == 0)
|
||||
{
|
||||
if (!value)
|
||||
;
|
||||
else if (!set_unicode_line_style(popt, value, vallen,
|
||||
&popt->topt.unicode_header_linestyle))
|
||||
{
|
||||
psql_error("\\pset: allowed unicode header linestyle are single, double\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* set border style/width */
|
||||
else if (strcmp(param, "border") == 0)
|
||||
{
|
||||
|
@ -2601,6 +2678,25 @@ printPsetInfo(const char *param, struct printQueryOpt *popt)
|
|||
printf(_("Tuples only (%s) is off.\n"), param);
|
||||
}
|
||||
|
||||
/* unicode style formatting */
|
||||
else if (strcmp(param, "unicode_border_linestyle") == 0)
|
||||
{
|
||||
printf(_("Unicode border linestyle is \"%s\".\n"),
|
||||
_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
|
||||
}
|
||||
|
||||
else if (strcmp(param, "unicode_column_linestyle") == 0)
|
||||
{
|
||||
printf(_("Unicode column linestyle is \"%s\".\n"),
|
||||
_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
|
||||
}
|
||||
|
||||
else if (strcmp(param, "unicode_header_linestyle") == 0)
|
||||
{
|
||||
printf(_("Unicode border linestyle is \"%s\".\n"),
|
||||
_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
psql_error("\\pset: unknown option: %s\n", param);
|
||||
|
|
|
@ -249,7 +249,8 @@ slashUsage(unsigned short int pager)
|
|||
ON(pset.popt.topt.format == PRINT_HTML));
|
||||
fprintf(output, _(" \\pset [NAME [VALUE]] set table output option\n"
|
||||
" (NAME := {format|border|expanded|fieldsep|fieldsep_zero|footer|null|\n"
|
||||
" numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager})\n"));
|
||||
" numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager|\n"
|
||||
" unicode_border_linestyle|unicode_column_linestyle|unicode_header_linestyle})\n"));
|
||||
fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"),
|
||||
ON(pset.popt.topt.tuples_only));
|
||||
fprintf(output, _(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n"));
|
||||
|
|
|
@ -89,35 +89,97 @@ const printTextFormat pg_asciiformat_old =
|
|||
false
|
||||
};
|
||||
|
||||
const printTextFormat pg_utf8format =
|
||||
{
|
||||
"unicode",
|
||||
/* Default unicode linestyle format */
|
||||
const printTextFormat pg_utf8format;
|
||||
|
||||
typedef struct unicodeStyleRowFormat {
|
||||
const char *horizontal;
|
||||
const char *vertical_and_right[2];
|
||||
const char *vertical_and_left[2];
|
||||
} unicodeStyleRowFormat;
|
||||
|
||||
typedef struct unicodeStyleColumnFormat {
|
||||
const char *vertical;
|
||||
const char *vertical_and_horizontal[2];
|
||||
const char *up_and_horizontal[2];
|
||||
const char *down_and_horizontal[2];
|
||||
} unicodeStyleColumnFormat;
|
||||
|
||||
typedef struct unicodeStyleBorderFormat {
|
||||
const char *up_and_right;
|
||||
const char *vertical;
|
||||
const char *down_and_right;
|
||||
const char *horizontal;
|
||||
const char *down_and_left;
|
||||
const char *left_and_right;
|
||||
} unicodeStyleBorderFormat;
|
||||
|
||||
typedef struct unicodeStyleFormat {
|
||||
unicodeStyleRowFormat row_style[2];
|
||||
unicodeStyleColumnFormat column_style[2];
|
||||
unicodeStyleBorderFormat border_style[2];
|
||||
const char *header_nl_left;
|
||||
const char *header_nl_right;
|
||||
const char *nl_left;
|
||||
const char *nl_right;
|
||||
const char *wrap_left;
|
||||
const char *wrap_right;
|
||||
bool wrap_right_border;
|
||||
} unicodeStyleFormat;
|
||||
|
||||
const unicodeStyleFormat unicode_style = {
|
||||
{
|
||||
/* ─, ┌, ┬, ┐ */
|
||||
{"\342\224\200", "\342\224\214", "\342\224\254", "\342\224\220"},
|
||||
/* ─, ├, ┼, ┤ */
|
||||
{"\342\224\200", "\342\224\234", "\342\224\274", "\342\224\244"},
|
||||
/* ─, └, ┴, ┘ */
|
||||
{"\342\224\200", "\342\224\224", "\342\224\264", "\342\224\230"},
|
||||
/* N/A, │, │, │ */
|
||||
{"", "\342\224\202", "\342\224\202", "\342\224\202"}
|
||||
{
|
||||
/* ─ */
|
||||
"\342\224\200",
|
||||
/* ├╟ */
|
||||
{"\342\224\234", "\342\225\237"},
|
||||
/* ┤╢ */
|
||||
{"\342\224\244", "\342\225\242"},
|
||||
},
|
||||
{
|
||||
/* ═ */
|
||||
"\342\225\220",
|
||||
/* ╞╠ */
|
||||
{"\342\225\236", "\342\225\240"},
|
||||
/* ╡╣ */
|
||||
{"\342\225\241", "\342\225\243"},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
/* │ */
|
||||
"\342\224\202",
|
||||
/* ┼╪ */
|
||||
{"\342\224\274", "\342\225\252"},
|
||||
/* ┴╧ */
|
||||
{"\342\224\264", "\342\225\247"},
|
||||
/* ┬╤ */
|
||||
{"\342\224\254", "\342\225\244"},
|
||||
},
|
||||
{
|
||||
/* ║ */
|
||||
"\342\225\221",
|
||||
/* ╫╬ */
|
||||
{"\342\225\253", "\342\225\254"},
|
||||
/* ╨╩ */
|
||||
{"\342\225\250", "\342\225\251"},
|
||||
/* ╥╦ */
|
||||
{"\342\225\245", "\342\225\246"},
|
||||
},
|
||||
},
|
||||
{
|
||||
/* └│┌─┐┘ */
|
||||
{"\342\224\224", "\342\224\202", "\342\224\214", "\342\224\200", "\342\224\220", "\342\224\230"},
|
||||
/* ╚║╔═╗╝ */
|
||||
{"\342\225\232", "\342\225\221", "\342\225\224", "\342\225\220", "\342\225\227", "\342\225\235"},
|
||||
},
|
||||
/* │ */
|
||||
"\342\224\202",
|
||||
/* │ */
|
||||
"\342\224\202",
|
||||
/* │ */
|
||||
"\342\224\202",
|
||||
" ",
|
||||
/* ↵ */
|
||||
"\342\206\265",
|
||||
"\342\206\265", /* ↵ */
|
||||
" ",
|
||||
/* ↵ */
|
||||
"\342\206\265",
|
||||
/* … */
|
||||
"\342\200\246",
|
||||
/* … */
|
||||
"\342\200\246",
|
||||
"\342\206\265", /* ↵ */
|
||||
"\342\200\246", /* … */
|
||||
"\342\200\246", /* … */
|
||||
true
|
||||
};
|
||||
|
||||
|
@ -1289,7 +1351,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||
}
|
||||
else
|
||||
/*
|
||||
* For border = 2, two more for the pipes (|) at the begging and
|
||||
* For border = 2, two more for the pipes (|) at the beginning and
|
||||
* at the end of the lines.
|
||||
*/
|
||||
swidth = 7;
|
||||
|
@ -2952,6 +3014,58 @@ get_line_style(const printTableOpt *opt)
|
|||
return &pg_asciiformat;
|
||||
}
|
||||
|
||||
void
|
||||
refresh_utf8format(const printTableOpt *opt)
|
||||
{
|
||||
printTextFormat *popt = (printTextFormat *) &pg_utf8format;
|
||||
|
||||
const unicodeStyleBorderFormat *border;
|
||||
const unicodeStyleRowFormat *header;
|
||||
const unicodeStyleColumnFormat *column;
|
||||
|
||||
popt->name = "unicode";
|
||||
|
||||
border = &unicode_style.border_style[opt->unicode_border_linestyle];
|
||||
header = &unicode_style.row_style[opt->unicode_header_linestyle];
|
||||
column = &unicode_style.column_style[opt->unicode_column_linestyle];
|
||||
|
||||
popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
|
||||
popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
|
||||
popt->lrule[PRINT_RULE_TOP].midvrule = column->down_and_horizontal[opt->unicode_border_linestyle];
|
||||
popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
|
||||
|
||||
popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
|
||||
popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle];
|
||||
popt->lrule[PRINT_RULE_MIDDLE].midvrule = column->vertical_and_horizontal[opt->unicode_header_linestyle];
|
||||
popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle];
|
||||
|
||||
popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
|
||||
popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
|
||||
popt->lrule[PRINT_RULE_BOTTOM].midvrule = column->up_and_horizontal[opt->unicode_border_linestyle];
|
||||
popt->lrule[PRINT_RULE_BOTTOM].rightvrule = border->left_and_right;
|
||||
|
||||
/* N/A */
|
||||
popt->lrule[PRINT_RULE_DATA].hrule = "";
|
||||
popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
|
||||
popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
|
||||
popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
|
||||
|
||||
popt->midvrule_nl = column->vertical;
|
||||
popt->midvrule_wrap = column->vertical;
|
||||
popt->midvrule_blank = column->vertical;
|
||||
|
||||
/* Same for all unicode today */
|
||||
popt->header_nl_left = unicode_style.header_nl_left;
|
||||
popt->header_nl_right = unicode_style.header_nl_right;
|
||||
popt->nl_left = unicode_style.nl_left;
|
||||
popt->nl_right = unicode_style.nl_right;
|
||||
popt->wrap_left = unicode_style.wrap_left;
|
||||
popt->wrap_right = unicode_style.wrap_right;
|
||||
popt->wrap_right_border = unicode_style.wrap_right_border;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the byte distance to the end of the string or *target_width
|
||||
* display character positions, whichever comes first. Update *target_width
|
||||
|
|
|
@ -68,6 +68,12 @@ typedef struct printTextFormat
|
|||
* marks when border=0? */
|
||||
} printTextFormat;
|
||||
|
||||
typedef enum unicode_linestyle
|
||||
{
|
||||
UNICODE_LINESTYLE_SINGLE = 0,
|
||||
UNICODE_LINESTYLE_DOUBLE
|
||||
} unicode_linestyle;
|
||||
|
||||
struct separator
|
||||
{
|
||||
char *separator;
|
||||
|
@ -97,6 +103,9 @@ typedef struct printTableOpt
|
|||
int encoding; /* character encoding */
|
||||
int env_columns; /* $COLUMNS on psql start, 0 is unset */
|
||||
int columns; /* target width for wrapped format */
|
||||
unicode_linestyle unicode_border_linestyle;
|
||||
unicode_linestyle unicode_column_linestyle;
|
||||
unicode_linestyle unicode_header_linestyle;
|
||||
} printTableOpt;
|
||||
|
||||
/*
|
||||
|
@ -178,6 +187,7 @@ extern void printQuery(const PGresult *result, const printQueryOpt *opt,
|
|||
|
||||
extern void setDecimalLocale(void);
|
||||
extern const printTextFormat *get_line_style(const printTableOpt *opt);
|
||||
extern void refresh_utf8format(const printTableOpt *opt);
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
#define DEFAULT_PAGER "more"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "help.h"
|
||||
#include "input.h"
|
||||
#include "mainloop.h"
|
||||
#include "print.h"
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
|
@ -131,6 +132,13 @@ main(int argc, char *argv[])
|
|||
pset.popt.topt.start_table = true;
|
||||
pset.popt.topt.stop_table = true;
|
||||
pset.popt.topt.default_footer = true;
|
||||
|
||||
pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE;
|
||||
pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE;
|
||||
pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE;
|
||||
|
||||
refresh_utf8format(&(pset.popt.topt));
|
||||
|
||||
/* We must get COLUMNS here before readline() sets it */
|
||||
pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
|
||||
|
||||
|
|
|
@ -3622,7 +3622,8 @@ psql_completion(const char *text, int start, int end)
|
|||
{"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
|
||||
"footer", "format", "linestyle", "null", "numericlocale",
|
||||
"pager", "recordsep", "recordsep_zero", "tableattr", "title",
|
||||
"tuples_only", NULL};
|
||||
"tuples_only", "unicode_border_linestyle",
|
||||
"unicode_column_linestyle", "unicode_header_linestyle", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST_CS(my_list);
|
||||
}
|
||||
|
@ -3643,6 +3644,16 @@ psql_completion(const char *text, int start, int end)
|
|||
|
||||
COMPLETE_WITH_LIST_CS(my_list);
|
||||
}
|
||||
else if (strcmp(prev_wd, "unicode_border_linestyle") == 0 ||
|
||||
strcmp(prev_wd, "unicode_column_linestyle") == 0 ||
|
||||
strcmp(prev_wd, "unicode_header_linestyle") == 0)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"single", "double", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST_CS(my_list);
|
||||
|
||||
}
|
||||
}
|
||||
else if (strcmp(prev_wd, "\\unset") == 0)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,9 @@ Record separator (recordsep) is <newline>.
|
|||
Table attributes (tableattr) unset.
|
||||
Title (title) unset.
|
||||
Tuples only (tuples_only) is off.
|
||||
Unicode border linestyle is "single".
|
||||
Unicode column linestyle is "single".
|
||||
Unicode border linestyle is "single".
|
||||
-- test multi-line headers, wrapping, and newline indicators
|
||||
prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab
|
||||
|
||||
|
|
Loading…
Reference in New Issue