Hi I removed dynamic allocation and reduced patch size.
What I tested a old unicode style is same as new unicode style. There nothing was changed .. some fields are specified in refresh_utf8format function Regards Pavel 2014-09-08 4:44 GMT+02:00 Stephen Frost <sfr...@snowman.net>: > Pavel, > > * Pavel Stehule (pavel.steh...@gmail.com) wrote: > > 2014-07-23 8:38 GMT+02:00 Tomas Vondra <t...@fuzzy.cz>: > > > OK, thanks. The new version seems OK to me. > > > > Thank you > > I've started looking over the patch and went back through the previous > thread about it. For my part, I'm in favor of adding this capability, > but I'm not terribly happy about how it was done. In particular, > get_line_style() seems pretty badly hacked around, and I don't really > like having the prepare_unicode_format call underneath it allocating > memory and then passing back up the need to free that memory via a new > field in the structure. Also, on a quick glance, are you sure that the > new 'unicode' output matches the same as the old 'unicode' did (with > pg_utf8format)? > > I would think we'd simply set up a structure which is updated when the > linestyle is changed, which is surely going to be much less frequently > than the request for which linestyle to use happens, and handle all of > the line styles in more-or-less the same way rather than doing something > completely different for unicode than for the others. > > Thanks, > > Stephen >
commit 509f8a92525889651653a75356d3fa57b58f3141 Author: Pavel Stehule <pavel.steh...@gooddata.com> Date: Mon Sep 8 17:18:43 2014 +0200 remove palloc diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index db314c3..84233d0 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -2299,6 +2299,42 @@ lo_import 152801 </para> </listitem> </varlistentry> + + <varlistentry> + <term><literal>unicode_border_style</literal></term> + <listitem> + <para> + Sets the border line drawing style to one + of <literal>single</literal> or <literal>double</literal> + This option only affects the <literal>unicode</> + linestyle + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>unicode_column_style</literal></term> + <listitem> + <para> + Sets the column line drawing style to one + of <literal>single</literal> or <literal>double</literal> + This option only affects the <literal>unicode</> + linestyle + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>unicode_header_style</literal></term> + <listitem> + <para> + Sets the header line drawing style to one + of <literal>single</literal> or <literal>double</literal> + This option only affects the <literal>unicode</> + linestyle + </para> + </listitem> + </varlistentry> </variablelist> </para> diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index a66093a..fd05aae 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -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,40 @@ _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 +2342,42 @@ 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 +2674,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); diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index f8f000f..4ca7887 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -235,7 +235,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")); diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 0b31bc1..75cafc2 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -89,36 +89,84 @@ const printTextFormat pg_asciiformat_old = false }; -const printTextFormat pg_utf8format = -{ - "unicode", - { - /* ─, ┌, ┬, ┐ */ - {"\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"} +/* Default unicode linestyle format */ +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]; +} unicodeStyleFormat; + +const unicodeStyleFormat unicode_style = { + { + { + /* ─ */ + "\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\200\246", - /* … */ - "\342\200\246", - true }; @@ -503,7 +551,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) bool opt_tuples_only = cont->opt->tuples_only; int encoding = cont->opt->encoding; unsigned short opt_border = cont->opt->border; - const printTextFormat *format = get_line_style(cont->opt); + printTextFormat *format = get_line_style(cont->opt); const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; unsigned int col_count = 0, @@ -1092,7 +1140,7 @@ print_aligned_vertical_line(const printTableContent *cont, printTextRule pos, FILE *fout) { - const printTextFormat *format = get_line_style(cont->opt); + printTextFormat *format = get_line_style(cont->opt); const printTextLineFormat *lformat = &format->lrule[pos]; unsigned short opt_border = cont->opt->border; unsigned int i; @@ -1146,7 +1194,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) { bool opt_tuples_only = cont->opt->tuples_only; unsigned short opt_border = cont->opt->border; - const printTextFormat *format = get_line_style(cont->opt); + printTextFormat *format = get_line_style(cont->opt); const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; int encoding = cont->opt->encoding; unsigned long record = cont->opt->prior_records + 1; @@ -2939,7 +2987,7 @@ setDecimalLocale(void) } /* get selected or default line style */ -const printTextFormat * +printTextFormat * get_line_style(const printTableOpt *opt) { /* @@ -2953,6 +3001,64 @@ 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; + popt->header_nl_left = " "; + + /* ↵ */ + popt->header_nl_right = "\342\206\265"; + + popt->nl_left = " "; + + /* ↵ */ + popt->nl_right = "\342\206\265"; + + /* … */ + popt->wrap_left = "\342\200\246"; + popt->wrap_right = "\342\200\246"; + + popt->wrap_right_border = true; + + return popt; +} + /* * Compute the byte distance to the end of the string or *target_width * display character positions, whichever comes first. Update *target_width diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index 87b2856..bb8c1fc 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -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; /* @@ -152,7 +161,7 @@ typedef struct printQueryOpt extern const printTextFormat pg_asciiformat; extern const printTextFormat pg_asciiformat_old; -extern const printTextFormat pg_utf8format; +extern printTextFormat pg_utf8format; extern FILE *PageOutput(int lines, unsigned short int pager); @@ -177,7 +186,9 @@ extern void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog); extern void setDecimalLocale(void); -extern const printTextFormat *get_line_style(const printTableOpt *opt); +extern printTextFormat *get_line_style(const printTableOpt *opt); +extern void refresh_utf8format(const printTableOpt *opt); + #ifndef __CYGWIN__ #define DEFAULT_PAGER "more" diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 5a397e8..8eecade 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -26,6 +26,7 @@ #include "help.h" #include "input.h" #include "mainloop.h" +#include "print.h" #include "settings.h" @@ -129,6 +130,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; diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 7577c4b..8b227f1 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3615,7 +3615,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); } @@ -3636,6 +3637,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) { diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 199036d..3764127 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -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
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers