Hi 2014-09-11 16:42 GMT+02:00 Stephen Frost <sfr...@snowman.net>:
> Pavel, > > * Pavel Stehule (pavel.steh...@gmail.com) wrote: > > I removed dynamic allocation and reduced patch size. > > This is certainly better, imv, though there are a couple of minor > issues (extra semi-colons, extraneous whitespace, get_line_style was > still changed to non-const, even though it doesn't need to be now). > fixed non-const -- other, I am sorry, I am blind > > > 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 > > I don't particularly like this (having these fields set in > refresh_utf8format to hard-coded strings in the function), why not have > those handled the same as the rest, where the strings themselves are in > the unicode_style structure? > I am not sure if I understand well. With refresh_utf8format I can do shortly 6 possible combinations - or more (when it will be requested) I have no idea how to write as rest without repeating all 6 combinations - what was one noticed issue of some older variant, where I designed unicode1, unicode2, ... Any idea, tip how to it? Regards Pavel > The rest looks pretty good. Need to step out for a bit but I'll look at > making the above changes when I get back if I don't hear anything. > > Thanks, > > Stephen >
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml new file mode 100644 index aa71674..1d59dce *** a/doc/src/sgml/ref/psql-ref.sgml --- b/doc/src/sgml/ref/psql-ref.sgml *************** lo_import 152801 *** 2306,2311 **** --- 2306,2347 ---- </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 new file mode 100644 index 5d90ca2..94d8f45 *** a/src/bin/psql/command.c --- b/src/bin/psql/command.c *************** exec_command(const char *cmd, *** 1054,1059 **** --- 1054,1062 ---- "footer", "format", "linestyle", "null", "numericlocale", "pager", "recordsep", "tableattr", "title", "tuples_only", + "unicode_border_linestyle", + "unicode_column_linestyle", + "unicode_header_linestyle", NULL }; *************** _align2string(enum printFormat in) *** 2248,2253 **** --- 2251,2290 ---- 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) *************** do_pset(const char *param, const char *v *** 2305,2310 **** --- 2342,2383 ---- } + /* 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) { *************** printPsetInfo(const char *param, struct *** 2601,2606 **** --- 2674,2698 ---- 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 new file mode 100644 index ef35696..6035a77 *** a/src/bin/psql/help.c --- b/src/bin/psql/help.c *************** slashUsage(unsigned short int pager) *** 249,255 **** 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")); 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")); --- 249,256 ---- 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" ! " 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 new file mode 100644 index 0b31bc1..39f8d6d *** a/src/bin/psql/print.c --- b/src/bin/psql/print.c *************** const printTextFormat pg_asciiformat_old *** 89,124 **** 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"} }, - /* │ */ - "\342\224\202", - /* │ */ - "\342\224\202", - /* │ */ - "\342\224\202", - " ", - /* ↵ */ - "\342\206\265", - " ", - /* ↵ */ - "\342\206\265", - /* … */ - "\342\200\246", - /* … */ - "\342\200\246", - true }; --- 89,172 ---- false }; ! /* 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]; ! } 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"}, }, }; *************** get_line_style(const printTableOpt *opt) *** 2953,2958 **** --- 3001,3064 ---- 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 new file mode 100644 index 87b2856..9bfa78a *** a/src/bin/psql/print.h --- b/src/bin/psql/print.h *************** typedef struct printTextFormat *** 68,73 **** --- 68,79 ---- * marks when border=0? */ } printTextFormat; + typedef enum unicode_linestyle + { + UNICODE_LINESTYLE_SINGLE = 0, + UNICODE_LINESTYLE_DOUBLE + } unicode_linestyle; + struct separator { char *separator; *************** typedef struct printTableOpt *** 97,102 **** --- 103,111 ---- 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; /* *************** extern void printQuery(const PGresult *r *** 178,183 **** --- 187,194 ---- 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" diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c new file mode 100644 index b879d0c..11a159a *** a/src/bin/psql/startup.c --- b/src/bin/psql/startup.c *************** *** 26,31 **** --- 26,32 ---- #include "help.h" #include "input.h" #include "mainloop.h" + #include "print.h" #include "settings.h" *************** main(int argc, char *argv[]) *** 131,136 **** --- 132,144 ---- 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 new file mode 100644 index 4ce47e9..b80fe13 *** a/src/bin/psql/tab-complete.c --- b/src/bin/psql/tab-complete.c *************** psql_completion(const char *text, int st *** 3622,3628 **** {"border", "columns", "expanded", "fieldsep", "fieldsep_zero", "footer", "format", "linestyle", "null", "numericlocale", "pager", "recordsep", "recordsep_zero", "tableattr", "title", ! "tuples_only", NULL}; COMPLETE_WITH_LIST_CS(my_list); } --- 3622,3629 ---- {"border", "columns", "expanded", "fieldsep", "fieldsep_zero", "footer", "format", "linestyle", "null", "numericlocale", "pager", "recordsep", "recordsep_zero", "tableattr", "title", ! "tuples_only", "unicode_border_linestyle", ! "unicode_column_linestyle", "unicode_header_linestyle", NULL}; COMPLETE_WITH_LIST_CS(my_list); } *************** psql_completion(const char *text, int st *** 3643,3648 **** --- 3644,3659 ---- 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 new file mode 100644 index 199036d..3764127 *** a/src/test/regress/expected/psql.out --- b/src/test/regress/expected/psql.out *************** Record separator (recordsep) is <newline *** 68,73 **** --- 68,76 ---- 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