printing table in asciidoc with psql
Hi,
I've been working a little bit on a patch for printing tables in asciidoc
with psql.
It's not finished yet, I'm not sure it there is any sense in supporting
border types etc. The code is not cleared so far, but any remarks on the
style not playing well with the normal postgres style of code are welcomed.
The code just works. With extended and normal modes. With table columns
made of funny characters, with alignment of data in table cells. I was
trying to implement it similar to the html export function, however
escaping of the strings was much easier, as the normal html-way
substitution is not easy to implement in asciidoc.
I'd like to ask you for any advices for this code.
thanks,
Szymon
Attachments:
asciidoc.1.patchtext/x-diff; charset=US-ASCII; name=asciidoc.1.patchDownload
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 2227db4..ae6b106 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2247,6 +2247,9 @@ _align2string(enum printFormat in)
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
@@ -2316,9 +2319,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3b3c3b7..236c8f3 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2475,6 +2475,180 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
}
}
+/*********************/
+/* ASCIIDOC **********/
+/*********************/
+
+static void
+print_asciidoc_text(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fprintf(fout, "[options=\"header\",cols=\"");
+ for(i = 0; i < cont->ncolumns; i++) {
+ if (i != 0) fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">literal" : "<literal");
+ }
+ fprintf(fout, "\"]\n");
+ fprintf(fout, "|====\n");
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ fputs("^| +++", fout);
+ fputs(*ptr, fout);
+ fputs("+++ ", fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fprintf(fout, "| ");
+
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ fputs(*ptr, fout);
+
+ fputs(" ", fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+
+
+ }
+
+ fprintf(fout, "|====\n");
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
+
+// TODO add support for cont->opt->border
+// TODO add support for additional options
+
+static void
+print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ const char *opt_table_attr = cont->opt->tableAttr;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fprintf(fout, "[cols=\"h,literal\"]\n");
+ fprintf(fout, "|====\n");
+
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^| Record %lu\n",
+ record++);
+ else
+ fputs("2| \n", fout);
+ }
+
+ fputs("|+++", fout);
+ fputs(cont->headers[i % cont->ncolumns], fout);
+ fputs("+++", fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ fputs(*ptr, fout);
+
+ fputs("\n", fout);
+ }
+
+ fprintf(fout, "|====\n");
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
/********************************/
/* Public functions */
@@ -2872,6 +3046,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
@@ -3100,3 +3280,5 @@ strlen_max_width(unsigned char *str, int *target_width, int encoding)
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index f668b23..cf885ad 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -20,7 +20,8 @@ enum printFormat
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b80fe13..a0c5230 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3633,7 +3633,7 @@ psql_completion(const char *text, int start, int end)
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
- "troff-ms", NULL};
+ "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
El 16/09/14 16:52, Szymon Guz escribi�:
Hi,
I've been working a little bit on a patch for printing tables in
asciidoc with psql.It's not finished yet, I'm not sure it there is any sense in
supporting border types etc. The code is not cleared so far, but any
remarks on the style not playing well with the normal postgres style
of code are welcomed.The code just works. With extended and normal modes. With table
columns made of funny characters, with alignment of data in table
cells. I was trying to implement it similar to the html export
function, however escaping of the strings was much easier, as the
normal html-way substitution is not easy to implement in asciidoc.I'd like to ask you for any advices for this code.
thanks,
Szymon
Please add "asciidoc" in src/bin/psql/help.c[354]
354,96-103
fprintf(output, _(" format set output format
[unaligned, aligned, wrapped, html, latex, ..]\n"));
Tested the patch and worked fine.
--
--
Emanuel Calvo http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
2014-09-16 21:52 GMT+02:00 Szymon Guz <mabewlun@gmail.com>:
Hi,
I've been working a little bit on a patch for printing tables in asciidoc
with psql.It's not finished yet, I'm not sure it there is any sense in supporting
border types etc. The code is not cleared so far, but any remarks on the
style not playing well with the normal postgres style of code are welcomed.The code just works. With extended and normal modes. With table columns
made of funny characters, with alignment of data in table cells. I was
trying to implement it similar to the html export function, however
escaping of the strings was much easier, as the normal html-way
substitution is not easy to implement in asciidoc.I'd like to ask you for any advices for this code.
nice +1
Pavel
Show quoted text
thanks,
Szymon--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 9/16/14 3:52 PM, Szymon Guz wrote:
It's not finished yet, I'm not sure it there is any sense in supporting
border types etc.
AFAICT, Asciidoc doesn't support border types, so (if so) you should
just ignore that setting.
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 17 September 2014 19:30, Peter Eisentraut <peter_e@gmx.net> wrote:
On 9/16/14 3:52 PM, Szymon Guz wrote:
It's not finished yet, I'm not sure it there is any sense in supporting
border types etc.AFAICT, Asciidoc doesn't support border types, so (if so) you should
just ignore that setting.
Too late, I've done something like this:
border=0
[frame="none",grid="none"]
border=1
[frame="all",grid="none"]
border=2
[frame="all",grid="all"]
thanks,
Szymon
On 17 September 2014 19:55, Szymon Guz <mabewlun@gmail.com> wrote:
On 17 September 2014 19:30, Peter Eisentraut <peter_e@gmx.net> wrote:
On 9/16/14 3:52 PM, Szymon Guz wrote:
It's not finished yet, I'm not sure it there is any sense in supporting
border types etc.AFAICT, Asciidoc doesn't support border types, so (if so) you should
just ignore that setting.Too late, I've done something like this:
border=0
[frame="none",grid="none"]border=1
[frame="all",grid="none"]border=2
[frame="all",grid="all"]thanks,
Szymon
Hi,
thanks for all the remarks.
I've attached another version of this patch.
I think it's done.
- This works: `\pset format asciidoc`
- Output is formatted as asciidoc tables.
- There is support for borders {0,1,2}. The attached html file was made by
running tests for psql, taking the asciidoc tables from it, converting to
html with `asciidoc file`.
-- border = 0 -> [frame="none",grid="none"]
-- border = 1 -> [frame="none",grid="all"]
-- border = 2 -> [frame="all",grid="all"]
- There are also tests.
-- For normal and extended mode combined with each of the border values.
-- With column names made of characters which need escaping
-- With values: (with escape needed characters, string '11' and integer 11
- they should have different right-left alignment).
- Documentation for psql is updated.
- According to Emanuel's advice: help.c is updated.
The attached html file contains tables from the test in this order:
normal, border 0
normal, border 1
normal, border 2
expanded, border 0
expanded, border 1
expanded, border 2
regards,
Szymon
Attachments:
asciidoc.2.patchtext/x-diff; charset=US-ASCII; name=asciidoc.2.patchDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index e7fcc73..cd64b88 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2092,8 +2092,8 @@ lo_import 152801
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
- <literal>latex-longtable</literal>, or
- <literal>troff-ms</literal>.
+ <literal>latex-longtable</literal>,
+ <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
@@ -2120,7 +2120,8 @@ lo_import 152801
<para>
The <literal>html</>, <literal>latex</>,
- <literal>latex-longtable</literal>, and <literal>troff-ms</>
+ <literal>latex-longtable</literal>, <literal>troff-ms</>,
+ and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 2227db4..ae6b106 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2247,6 +2247,9 @@ _align2string(enum printFormat in)
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
@@ -2316,9 +2319,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 6035a77..66da6ec 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -351,7 +351,7 @@ helpVariables(unsigned short int pager)
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
- fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
+ fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3b3c3b7..956bbb1 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2475,6 +2475,200 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
}
}
+/*********************/
+/* ASCIIDOC **********/
+/*********************/
+
+static void
+print_asciidoc_text(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++) {
+ if (i != 0) fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">literal" : "<literal");
+ }
+ fputs("\"", fout);
+ switch (opt_border) {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ fputs("^| +++", fout);
+ fputs(*ptr, fout);
+ fputs("+++ ", fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fprintf(fout, "| ");
+
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ fputs(*ptr, fout);
+
+ fputs(" ", fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
+
+static void
+print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,literal\"", fout);
+ switch (opt_border) {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^| Record %lu\n",
+ record++);
+ else
+ fputs("2| \n", fout);
+ }
+
+ fputs("|+++", fout);
+ fputs(cont->headers[i % cont->ncolumns], fout);
+ fputs("+++", fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ fputs(*ptr, fout);
+
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
/********************************/
/* Public functions */
@@ -2872,6 +3066,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index f668b23..cf885ad 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -20,7 +20,8 @@ enum printFormat
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b80fe13..a0c5230 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3633,7 +3633,7 @@ psql_completion(const char *text, int start, int end)
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
- "troff-ms", NULL};
+ "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 3764127..4544c69 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -2123,3 +2123,203 @@ execute q;
+------------------+-------------------+
deallocate q;
+prepare q as select 'lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as "012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+[options="header",cols="<literal,<literal,>literal",frame="none",grid="none"]
+|====
+^| +++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ ^| +++0123456789+++ ^| +++int+++
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 1
+execute q;
+[options="header",cols="<literal,<literal,>literal",frame="none"]
+|====
+^| +++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ ^| +++0123456789+++ ^| +++int+++
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 2
+execute q;
+[options="header",cols="<literal,<literal,>literal",frame="all",grid="all"]
+|====
+^| +++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ ^| +++0123456789+++ ^| +++int+++
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset expanded on
+\pset border 0
+execute q;
+[cols="h,literal",frame="none",grid="none"]
+|====
+2+^| Record 1
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 2
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 3
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 4
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 5
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 6
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 7
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 8
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 9
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 10
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+|====
+\pset border 1
+execute q;
+[cols="h,literal",frame="none"]
+|====
+2+^| Record 1
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 2
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 3
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 4
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 5
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 6
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 7
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 8
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 9
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 10
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+|====
+\pset border 2
+execute q;
+[cols="h,literal",frame="all",grid="all"]
+|====
+2+^| Record 1
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 2
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 3
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 4
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 5
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 6
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 7
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 8
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 9
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+2+^| Record 10
+|+++012345678 9abc def!*@#&!@(*&*~~_+-=\ \+++ <|lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+|+++0123456789+++ <|11
+|+++int+++ >|11
+|====
+deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 5ccc68f..6537c53 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -276,3 +276,28 @@ execute q;
execute q;
deallocate q;
+
+prepare q as select 'lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as "012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+\pset expanded on
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+deallocate q;
Hi Szymon
I found a small bug - it doesn't escape "|" well
postgres=# select * from mytab ;
a | numeric_b | c
----------+-----------+------------
Ahoj | 10 | 2014-10-17
Hello | 20 | 2014-10-18
Hi | 30 | 2014-10-19
aaa|aaaa | 2222 | 2014-10-17
(4 rows)
result
[options="header",cols="<literal,>literal,<literal",frame="all",grid="all"]
|====
^| +++a+++ ^| +++numeric_b+++ ^| +++c+++
| Ahoj | 10 | 2014-10-17
| Hello | 20 | 2014-10-18
| Hi | 30 | 2014-10-19
| aaa|aaaa | 2222 | 2014-10-17
|====
Next, I tested it with asciidoc and asciidoctor and I have a problem with
asciidoctor - it doesn't respect aligning .. so numbers are aligned to left
instead to right.
When you use a option "header" then a formatting "+++xxxx++++" is useless.
Regards
Pavel
2014-09-17 21:26 GMT+02:00 Szymon Guz <mabewlun@gmail.com>:
Show quoted text
On 17 September 2014 19:55, Szymon Guz <mabewlun@gmail.com> wrote:
On 17 September 2014 19:30, Peter Eisentraut <peter_e@gmx.net> wrote:
On 9/16/14 3:52 PM, Szymon Guz wrote:
It's not finished yet, I'm not sure it there is any sense in supporting
border types etc.AFAICT, Asciidoc doesn't support border types, so (if so) you should
just ignore that setting.Too late, I've done something like this:
border=0
[frame="none",grid="none"]border=1
[frame="all",grid="none"]border=2
[frame="all",grid="all"]thanks,
SzymonHi,
thanks for all the remarks.I've attached another version of this patch.
I think it's done.
- This works: `\pset format asciidoc`
- Output is formatted as asciidoc tables.
- There is support for borders {0,1,2}. The attached html file was made by
running tests for psql, taking the asciidoc tables from it, converting to
html with `asciidoc file`.
-- border = 0 -> [frame="none",grid="none"]
-- border = 1 -> [frame="none",grid="all"]
-- border = 2 -> [frame="all",grid="all"]- There are also tests.
-- For normal and extended mode combined with each of the border values.
-- With column names made of characters which need escaping
-- With values: (with escape needed characters, string '11' and integer 11
- they should have different right-left alignment).- Documentation for psql is updated.
- According to Emanuel's advice: help.c is updated.
The attached html file contains tables from the test in this order:
normal, border 0
normal, border 1
normal, border 2
expanded, border 0
expanded, border 1
expanded, border 2regards,
Szymon--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 17 October 2014 09:01, Pavel Stehule <pavel.stehule@gmail.com> wrote:
Hi Szymon
I found a small bug - it doesn't escape "|" well
postgres=# select * from mytab ;
a | numeric_b | c
----------+-----------+------------
Ahoj | 10 | 2014-10-17
Hello | 20 | 2014-10-18
Hi | 30 | 2014-10-19
aaa|aaaa | 2222 | 2014-10-17
(4 rows)result
[options="header",cols="<literal,>literal,<literal",frame="all",grid="all"]
|====
^| +++a+++ ^| +++numeric_b+++ ^| +++c+++
| Ahoj | 10 | 2014-10-17
| Hello | 20 | 2014-10-18
| Hi | 30 | 2014-10-19
| aaa|aaaa | 2222 | 2014-10-17
|====Next, I tested it with asciidoc and asciidoctor and I have a problem with
asciidoctor - it doesn't respect aligning .. so numbers are aligned to left
instead to right.When you use a option "header" then a formatting "+++xxxx++++" is useless.
Hi Pavel,
thanks for the remarks. I've attached another version of the pach. It works
a little better now, including escaping | and asciidoctor alignment support.
thanks,
Szymon
Attachments:
asciidoc.3.patchtext/x-diff; charset=US-ASCII; name=asciidoc.3.patchDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index e7fcc73..cd64b88 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2092,8 +2092,8 @@ lo_import 152801
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
- <literal>latex-longtable</literal>, or
- <literal>troff-ms</literal>.
+ <literal>latex-longtable</literal>,
+ <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
@@ -2120,7 +2120,8 @@ lo_import 152801
<para>
The <literal>html</>, <literal>latex</>,
- <literal>latex-longtable</literal>, and <literal>troff-ms</>
+ <literal>latex-longtable</literal>, <literal>troff-ms</>,
+ and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 26089352..e00e47b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2248,6 +2248,9 @@ _align2string(enum printFormat in)
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
@@ -2321,9 +2324,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index ae5fe88..b14b313 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -351,7 +351,7 @@ helpVariables(unsigned short int pager)
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
- fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
+ fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3b3c3b7..83f268a 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2475,6 +2475,217 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
}
}
+/*********************/
+/* ASCIIDOC **********/
+/*********************/
+
+static void
+asciidoc_escaped_print(const char *in, FILE *fout)
+{
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+}
+
+static void
+print_asciidoc_text(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++) {
+ if (i != 0) fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border) {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ fputs("^l| ", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ fputs(" ", fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fprintf(fout, "| ");
+
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ fputs(" ", fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
+
+static void
+print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border) {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^| Record %lu\n",
+ record++);
+ else
+ fputs("2| \n", fout);
+ }
+
+ fputs("<|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+ fputs(" ", fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+
+ }
+}
/********************************/
/* Public functions */
@@ -2872,6 +3083,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
@@ -3100,3 +3317,5 @@ strlen_max_width(unsigned char *str, int *target_width, int encoding)
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index f668b23..cf885ad 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -20,7 +20,8 @@ enum printFormat
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 886188c..042f147 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3785,7 +3785,7 @@ psql_completion(const char *text, int start, int end)
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
- "troff-ms", NULL};
+ "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index e87b82b..5f5fac0 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -2125,3 +2125,203 @@ execute q;
+------------------+-------------------+
deallocate q;
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+[options="header",cols="<l,<l,>l",frame="none",grid="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 1
+execute q;
+[options="header",cols="<l,<l,>l",frame="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 2
+execute q;
+[options="header",cols="<l,<l,>l",frame="all",grid="all"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset expanded on
+\pset border 0
+execute q;
+[cols="h,l",frame="none",grid="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 1
+execute q;
+[cols="h,l",frame="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 2
+execute q;
+[cols="h,l",frame="all",grid="all"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 5ccc68f..fa1df8b 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -276,3 +276,28 @@ execute q;
execute q;
deallocate q;
+
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+\pset expanded on
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+deallocate q;
2014-10-29 12:23 GMT+01:00 Szymon Guz <mabewlun@gmail.com>:
On 17 October 2014 09:01, Pavel Stehule <pavel.stehule@gmail.com> wrote:
Hi Szymon
I found a small bug - it doesn't escape "|" well
postgres=# select * from mytab ;
a | numeric_b | c
----------+-----------+------------
Ahoj | 10 | 2014-10-17
Hello | 20 | 2014-10-18
Hi | 30 | 2014-10-19
aaa|aaaa | 2222 | 2014-10-17
(4 rows)result
[options="header",cols="<literal,>literal,<literal",frame="all",grid="all"]
|====
^| +++a+++ ^| +++numeric_b+++ ^| +++c+++
| Ahoj | 10 | 2014-10-17
| Hello | 20 | 2014-10-18
| Hi | 30 | 2014-10-19
| aaa|aaaa | 2222 | 2014-10-17
|====Next, I tested it with asciidoc and asciidoctor and I have a problem with
asciidoctor - it doesn't respect aligning .. so numbers are aligned to left
instead to right.When you use a option "header" then a formatting "+++xxxx++++" is useless.
Hi Pavel,
thanks for the remarks. I've attached another version of the pach. It
works a little better now, including escaping | and asciidoctor alignment
support.
it is fixed. Thank you.
I fixed formatting - please, recheck it.
I don't see any issue - it should be ready for commiter
Regards
Pavel
Show quoted text
thanks,
Szymon
Attachments:
asciidoc.4.patchtext/x-patch; charset=US-ASCII; name=asciidoc.4.patchDownload
commit f8ffd152aaa78ac1c96f808761680b8e593528a2
Author: Pavel Stehule <pavel.stehule@gooddata.com>
Date: Thu Oct 30 09:02:59 2014 +0100
fix formatting
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index e7fcc73..cd64b88 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2092,8 +2092,8 @@ lo_import 152801
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
- <literal>latex-longtable</literal>, or
- <literal>troff-ms</literal>.
+ <literal>latex-longtable</literal>,
+ <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
@@ -2120,7 +2120,8 @@ lo_import 152801
<para>
The <literal>html</>, <literal>latex</>,
- <literal>latex-longtable</literal>, and <literal>troff-ms</>
+ <literal>latex-longtable</literal>, <literal>troff-ms</>,
+ and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 26089352..e00e47b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2248,6 +2248,9 @@ _align2string(enum printFormat in)
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
@@ -2321,9 +2324,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index ae5fe88..b14b313 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -351,7 +351,7 @@ helpVariables(unsigned short int pager)
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
- fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
+ fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3b3c3b7..ae98ff9 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2475,6 +2475,216 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
}
}
+/*************************/
+/* ASCIIDOC */
+/*************************/
+
+static void
+asciidoc_escaped_print(const char *in, FILE *fout)
+{
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+}
+
+static void
+print_asciidoc_text(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ fputs("^l| ", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ fputs(" ", fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fprintf(fout, "| ");
+
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ fputs(" ", fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+}
+
+static void
+print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^| Record %lu\n",
+ record++);
+ else
+ fputs("2| \n", fout);
+ }
+
+ fputs("<|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+ fputs(" ", fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+}
/********************************/
/* Public functions */
@@ -2872,6 +3082,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
@@ -3100,3 +3316,5 @@ strlen_max_width(unsigned char *str, int *target_width, int encoding)
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index f668b23..cf885ad 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -20,7 +20,8 @@ enum printFormat
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 886188c..042f147 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3785,7 +3785,7 @@ psql_completion(const char *text, int start, int end)
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
- "troff-ms", NULL};
+ "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index e87b82b..5f5fac0 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -2125,3 +2125,203 @@ execute q;
+------------------+-------------------+
deallocate q;
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+[options="header",cols="<l,<l,>l",frame="none",grid="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 1
+execute q;
+[options="header",cols="<l,<l,>l",frame="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 2
+execute q;
+[options="header",cols="<l,<l,>l",frame="all",grid="all"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset expanded on
+\pset border 0
+execute q;
+[cols="h,l",frame="none",grid="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 1
+execute q;
+[cols="h,l",frame="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 2
+execute q;
+[cols="h,l",frame="all",grid="all"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 5ccc68f..fa1df8b 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -276,3 +276,28 @@ execute q;
execute q;
deallocate q;
+
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+\pset expanded on
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+deallocate q;
On 30 October 2014 09:04, Pavel Stehule <pavel.stehule@gmail.com> wrote:
2014-10-29 12:23 GMT+01:00 Szymon Guz <mabewlun@gmail.com>:
On 17 October 2014 09:01, Pavel Stehule <pavel.stehule@gmail.com> wrote:
Hi Szymon
I found a small bug - it doesn't escape "|" well
postgres=# select * from mytab ;
a | numeric_b | c
----------+-----------+------------
Ahoj | 10 | 2014-10-17
Hello | 20 | 2014-10-18
Hi | 30 | 2014-10-19
aaa|aaaa | 2222 | 2014-10-17
(4 rows)result
[options="header",cols="<literal,>literal,<literal",frame="all",grid="all"]
|====
^| +++a+++ ^| +++numeric_b+++ ^| +++c+++
| Ahoj | 10 | 2014-10-17
| Hello | 20 | 2014-10-18
| Hi | 30 | 2014-10-19
| aaa|aaaa | 2222 | 2014-10-17
|====Next, I tested it with asciidoc and asciidoctor and I have a problem
with asciidoctor - it doesn't respect aligning .. so numbers are aligned to
left instead to right.When you use a option "header" then a formatting "+++xxxx++++" is
useless.Hi Pavel,
thanks for the remarks. I've attached another version of the pach. It
works a little better now, including escaping | and asciidoctor alignment
support.it is fixed. Thank you.
I fixed formatting - please, recheck it.
I don't see any issue - it should be ready for commiter
Regards
Pavel
Hi Pavel,
thanks for the review and reformatting. It looks much better after the
reformatting.
thanks,
Szymon
2014-10-30 9:30 GMT+01:00 Szymon Guz <mabewlun@gmail.com>:
On 30 October 2014 09:04, Pavel Stehule <pavel.stehule@gmail.com> wrote:
2014-10-29 12:23 GMT+01:00 Szymon Guz <mabewlun@gmail.com>:
On 17 October 2014 09:01, Pavel Stehule <pavel.stehule@gmail.com> wrote:
Hi Szymon
I found a small bug - it doesn't escape "|" well
postgres=# select * from mytab ;
a | numeric_b | c
----------+-----------+------------
Ahoj | 10 | 2014-10-17
Hello | 20 | 2014-10-18
Hi | 30 | 2014-10-19
aaa|aaaa | 2222 | 2014-10-17
(4 rows)result
[options="header",cols="<literal,>literal,<literal",frame="all",grid="all"]
|====
^| +++a+++ ^| +++numeric_b+++ ^| +++c+++
| Ahoj | 10 | 2014-10-17
| Hello | 20 | 2014-10-18
| Hi | 30 | 2014-10-19
| aaa|aaaa | 2222 | 2014-10-17
|====Next, I tested it with asciidoc and asciidoctor and I have a problem
with asciidoctor - it doesn't respect aligning .. so numbers are aligned to
left instead to right.When you use a option "header" then a formatting "+++xxxx++++" is
useless.Hi Pavel,
thanks for the remarks. I've attached another version of the pach. It
works a little better now, including escaping | and asciidoctor alignment
support.it is fixed. Thank you.
I fixed formatting - please, recheck it.
I don't see any issue - it should be ready for commiter
Regards
Pavel
Hi Pavel,
thanks for the review and reformatting. It looks much better after the
reformatting.
ok
so
1. There are no any objections against proposed and implemented feature.
This patch contains just implementation of asciidoc format and nothing
else. It has zero impact on current code.
2. There are no problems with patching and compilation. All current regress
tests passed.
3. Patch contains doc and small set of regress tests.
4. I tested output against asciidoc and asciidoctor, I didn't find any
problems.
This patch is ready for commiter
Thank you for patch
Regards
Pavel
Show quoted text
thanks,
Szymon
I did \o /tmp/tst, then
\dS
create table "eh | oh" ();
\dS
and then filtered the output file to HTML. The CREATE TABLE tag ended
up in the same line as the title of the following table. I think
there's a newline is missing somewhere.
The good news is that the | in the table name was processed correctly;
but I noticed that the table title is not using the escaped print, so I
would imagine that if I put a | in the title, things would go wrong.
(I don't know how to put titles on tables other than editing the
hardcoded titles for \ commands in psql).
Another thing is that spaces around the | seem gratuituous and produce
bad results. I tried "select * from pg_class" which results in a very
wide table, and then the HTML output contains some cells with the values
in the second line; this makes all rows taller than they must be,
because some cells use the first line and other cells in the same row
use the second line for the text. I hand-edited the asciidoc and
removed the spaces around | which makes the result nicer. (Maybe
removing the trailing space is enough.)
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Is anyone going to submit a new version of this patch?
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 14 November 2014 20:57, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
Is anyone going to submit a new version of this patch?
Hi Alvaro,
due to family issues I will not be able to work on it for the next 10 days.
regards,
Szymon
Hi
I can fix reported bugs today or tomorrow
Regards
Pavel
2014-11-14 21:00 GMT+01:00 Szymon Guz <mabewlun@gmail.com>:
Show quoted text
On 14 November 2014 20:57, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:Is anyone going to submit a new version of this patch?
Hi Alvaro,
due to family issues I will not be able to work on it for the next 10 days.regards,
Szymon
Hi
2014-11-07 22:37 GMT+01:00 Alvaro Herrera <alvherre@2ndquadrant.com>:
I did \o /tmp/tst, then
\dS
create table "eh | oh" ();
\dSand then filtered the output file to HTML. The CREATE TABLE tag ended
up in the same line as the title of the following table. I think
there's a newline is missing somewhere.
The good news is that the | in the table name was processed correctly;
but I noticed that the table title is not using the escaped print, so I
would imagine that if I put a | in the title, things would go wrong.
(I don't know how to put titles on tables other than editing the
hardcoded titles for \ commands in psql).Another thing is that spaces around the | seem gratuituous and produce
bad results. I tried "select * from pg_class" which results in a very
wide table, and then the HTML output contains some cells with the values
in the second line; this makes all rows taller than they must be,
because some cells use the first line and other cells in the same row
use the second line for the text. I hand-edited the asciidoc and
removed the spaces around | which makes the result nicer. (Maybe
removing the trailing space is enough.)
I see a trailing spaces, but I don't see a described effect. Please, can
you send some more specific test case?
I fixed a status view and removing trailing spaces
Regards
Pavel
Show quoted text
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
asciidoc.5.patchtext/x-patch; charset=US-ASCII; name=asciidoc.5.patchDownload
commit 76e033f3a287115f15f249c657b544c148e2efd2
Author: Pavel Stehule <pavel.stehule@gooddata.com>
Date: Sun Nov 16 23:38:46 2014 +0100
every table is in own paragraph
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index e7fcc73..cd64b88 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2092,8 +2092,8 @@ lo_import 152801
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
- <literal>latex-longtable</literal>, or
- <literal>troff-ms</literal>.
+ <literal>latex-longtable</literal>,
+ <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
@@ -2120,7 +2120,8 @@ lo_import 152801
<para>
The <literal>html</>, <literal>latex</>,
- <literal>latex-longtable</literal>, and <literal>troff-ms</>
+ <literal>latex-longtable</literal>, <literal>troff-ms</>,
+ and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 26089352..e00e47b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2248,6 +2248,9 @@ _align2string(enum printFormat in)
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
@@ -2321,9 +2324,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 66d80b5..ea8b9c1 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -858,6 +858,10 @@ PrintQueryStatus(PGresult *results)
html_escaped_print(PQcmdStatus(results), pset.queryFout);
fputs("</p>\n", pset.queryFout);
}
+ else if (pset.popt.topt.format == PRINT_ASCIIDOC)
+ {
+ fprintf(pset.queryFout, "\n%s\n", PQcmdStatus(results));
+ }
else
fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index ae5fe88..b14b313 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -351,7 +351,7 @@ helpVariables(unsigned short int pager)
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
- fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
+ fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3b3c3b7..3a8eb26 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2475,6 +2475,232 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
}
}
+/*************************/
+/* ASCIIDOC */
+/*************************/
+
+static void
+asciidoc_escaped_print(const char *in, FILE *fout)
+{
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+}
+
+static void
+print_asciidoc_text(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ fputs("^l| ", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ fputs(" ", fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if (((*ptr)[strspn(*ptr, " \t")] == '\0') || ((*ptr)[strspn(*ptr, " ")] == '\0'))
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ {
+ fputs(" ", fout);
+ continue;
+ }
+ }
+ else
+ {
+ fputs(" ", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ else
+ fputs(" ", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+}
+
+static void
+print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+{
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^| Record %lu\n",
+ record++);
+ else
+ fputs("2| \n", fout);
+ }
+
+ fputs("<|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+ fputs(" ", fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+}
/********************************/
/* Public functions */
@@ -2872,6 +3098,12 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
@@ -3100,3 +3332,5 @@ strlen_max_width(unsigned char *str, int *target_width, int encoding)
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index f668b23..08b6f24 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -20,7 +20,8 @@ enum printFormat
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 8c85425..728985e 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3787,7 +3787,7 @@ psql_completion(const char *text, int start, int end)
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
- "troff-ms", NULL};
+ "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index e87b82b..6e789b4 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -2125,3 +2125,209 @@ execute q;
+------------------+-------------------+
deallocate q;
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+
+[options="header",cols="<l,<l,>l",frame="none",grid="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 1
+execute q;
+
+[options="header",cols="<l,<l,>l",frame="none"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset border 2
+execute q;
+
+[options="header",cols="<l,<l,>l",frame="all",grid="all"]
+|====
+^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+|====
+
+....
+(10 rows)
+....
+\pset expanded on
+\pset border 0
+execute q;
+
+[cols="h,l",frame="none",grid="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 1
+execute q;
+
+[cols="h,l",frame="none"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+\pset border 2
+execute q;
+
+[cols="h,l",frame="all",grid="all"]
+|====
+2+^| Record 1
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 2
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 3
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 4
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 5
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 6
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 7
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 8
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 9
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+2+^| Record 10
+<| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+<|0123456789 <|11
+<|int >|11
+|====
+deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 5ccc68f..fa1df8b 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -276,3 +276,28 @@ execute q;
execute q;
deallocate q;
+
+prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+\pset format asciidoc
+\pset expanded off
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+\pset expanded on
+\pset border 0
+execute q;
+
+\pset border 1
+execute q;
+
+\pset border 2
+execute q;
+
+deallocate q;
On Mon, Nov 17, 2014 at 7:48 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
2014-11-07 22:37 GMT+01:00 Alvaro Herrera <alvherre@2ndquadrant.com>:
I did \o /tmp/tst, then
\dS
create table "eh | oh" ();
\dSand then filtered the output file to HTML. The CREATE TABLE tag ended
up in the same line as the title of the following table. I think
there's a newline is missing somewhere.The good news is that the | in the table name was processed correctly;
but I noticed that the table title is not using the escaped print, so I
would imagine that if I put a | in the title, things would go wrong.
(I don't know how to put titles on tables other than editing the
hardcoded titles for \ commands in psql).Another thing is that spaces around the | seem gratuituous and produce
bad results. I tried "select * from pg_class" which results in a very
wide table, and then the HTML output contains some cells with the values
in the second line; this makes all rows taller than they must be,
because some cells use the first line and other cells in the same row
use the second line for the text. I hand-edited the asciidoc and
removed the spaces around | which makes the result nicer. (Maybe
removing the trailing space is enough.)I see a trailing spaces, but I don't see a described effect. Please, can you
send some more specific test case?
This formatting problem is trivial to reproduce:
=# create table "foo" ();
CREATE TABLE
Time: 9.826 ms
=# \d
.List of relations
[options="header",cols="<l,<l,
<l,<l",frame="none"]
|====
^l| Schema ^l| Name ^l| Type ^l| Owner
| public | foo | table | ioltas
|====
....
(1 row)
....
I just tested this patch, and yes I agree with Alvaro that it would be
good to minimize the extra spaces around the table separators '|'. Now
we need to be careful as well, and I think that we should just remove
the separators on the right of the separators as cells values
controlling for example spans would result in incorrect output, stuff
like that:
5 2.2+^.^
9 2+>
Also, something a bit surprising is that this format produces always
one newline for each command, for example in the case of a DDL:
=# create table foo ();
CREATE TABLE
I think that this extra space should be removed as well, no?
This patch has been marked as "Waiting on Author" for a couple of
weeks, and the problems mentioned before have not been completely
addressed, hence marking this patch as returned with feedback. It
would be nice to see progress for the next CF.
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Dec 3, 2014 at 3:52 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
This patch has been marked as "Waiting on Author" for a couple of
weeks, and the problems mentioned before have not been completely
addressed, hence marking this patch as returned with feedback. It
would be nice to see progress for the next CF.
Btw, here is a resource showing table formatting in asciidoc:
http://asciidoc.org/newtables.html
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Dec 3, 2014 at 03:52:30PM +0900, Michael Paquier wrote:
I see a trailing spaces, but I don't see a described effect. Please, can you
send some more specific test case?This formatting problem is trivial to reproduce:
=# create table "foo" ();CREATE TABLE
Time: 9.826 ms
=# \d.List of relations
[options="header",cols="<l,<l,
<l,<l",frame="none"]
|====
^l| Schema ^l| Name ^l| Type ^l| Owner
| public | foo | table | ioltas
|====....
(1 row)
....I just tested this patch, and yes I agree with Alvaro that it would be
good to minimize the extra spaces around the table separators '|'. Now
we need to be careful as well, and I think that we should just remove
the separators on the right of the separators as cells values
controlling for example spans would result in incorrect output, stuff
like that:
5 2.2+^.^
9 2+>Also, something a bit surprising is that this format produces always
one newline for each command, for example in the case of a DDL:
=# create table foo ();CREATE TABLE
I think that this extra space should be removed as well, no?This patch has been marked as "Waiting on Author" for a couple of
weeks, and the problems mentioned before have not been completely
addressed, hence marking this patch as returned with feedback. It
would be nice to see progress for the next CF.
I was able to fix all the reported problems with the attached patch.
I used this for testing the output:
Is it OK now?
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a637001..82a91ec
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2092,2099 ****
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>, or
! <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
--- 2092,2099 ----
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>,
! <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
*************** lo_import 152801
*** 2120,2126 ****
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
--- 2120,2127 ----
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, <literal>troff-ms</>,
! and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 7c9f28d..a96f0ef
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2257,2262 ****
--- 2257,2265 ----
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
*************** do_pset(const char *param, const char *v
*** 2330,2338 ****
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2333,2343 ----
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index ac0dc27..93a517e
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index ce0d05d..09c5621
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_troff_ms_vertical(const printTable
*** 2476,2481 ****
--- 2476,2702 ----
}
}
+ /*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if (((*ptr)[strspn(*ptr, " \t")] == '\0'))
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ {
+ fputs(" ", fout);
+ continue;
+ }
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2|\n", fout);
+ }
+
+ fputs("<|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
/********************************/
/* Public functions */
*************** printTable(const printTableContent *cont
*** 2873,2878 ****
--- 3094,3105 ----
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
*************** strlen_max_width(unsigned char *str, int
*** 3101,3103 ****
--- 3328,3332 ----
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index a1a89d0..a7eff99
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 20,26 ****
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS
/* add your favourite output format here ... */
};
--- 20,27 ----
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS,
! PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..82653f7
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3791,3797 ****
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3791,3797 ----
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index e87b82b..6e789b4
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2125,2127 ****
--- 2125,2333 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l| 0123456789 ^l| int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& | 11 | 11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^| Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^| Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^| Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^| Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On Fri, Mar 20, 2015 at 11:10 PM, Bruce Momjian wrote:
I was able to fix all the reported problems with the attached patch.
I used this for testing the output:Is it OK now?
This does not work:
=# create table "5 2.2+^.^" ();
CREATE TABLE
=# \pset format asciidoc
Output format is asciidoc.
=# \d
.List of relations
[options="header",cols="<l,<l,<l,<l",frame="none"]
|====
^l|Schema ^l|Name ^l|Type ^l|Owner
|public|5 2.2+^.^|table|ioltas
|====
....
(1 row)
....
I think that we should really put additional spaces on the left side
of the column separators "|". For example, this line:
|public|5 2.2+^.^|table|ioltas
should become that:
|public |5 2.2+^.^ |table |ioltas
And there is no problem.
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sat, Mar 21, 2015 at 09:20:03PM +0900, Michael Paquier wrote:
This does not work:
=# create table "5 2.2+^.^" ();
CREATE TABLE
=# \pset format asciidoc
Output format is asciidoc.
=# \d.List of relations
[options="header",cols="<l,<l,<l,<l",frame="none"]
|====
^l|Schema ^l|Name ^l|Type ^l|Owner
|public|5 2.2+^.^|table|ioltas
|====....
(1 row)
....I think that we should really put additional spaces on the left side
of the column separators "|". For example, this line:
|public|5 2.2+^.^|table|ioltas
should become that:
|public |5 2.2+^.^ |table |ioltas
And there is no problem.
I have updated the attached patch to do as you suggested. Please also
test the \x output. Thanks.
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a637001..82a91ec
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2092,2099 ****
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>, or
! <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
--- 2092,2099 ----
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>,
! <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
*************** lo_import 152801
*** 2120,2126 ****
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
--- 2120,2127 ----
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, <literal>troff-ms</>,
! and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 7c9f28d..a96f0ef
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2257,2262 ****
--- 2257,2265 ----
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
*************** do_pset(const char *param, const char *v
*** 2330,2338 ****
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2333,2343 ----
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index ac0dc27..93a517e
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index ce0d05d..6a32b5c
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_troff_ms_vertical(const printTable
*** 2476,2481 ****
--- 2476,2704 ----
}
}
+ /*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ if (i != 0)
+ fputs(" ", fout);
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if (((*ptr)[strspn(*ptr, " \t")] == '\0'))
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ {
+ fputs(" ", fout);
+ continue;
+ }
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2|\n", fout);
+ }
+
+ fputs("<|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
/********************************/
/* Public functions */
*************** printTable(const printTableContent *cont
*** 2873,2878 ****
--- 3096,3107 ----
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
*************** strlen_max_width(unsigned char *str, int
*** 3101,3103 ****
--- 3330,3334 ----
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index a1a89d0..a7eff99
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 20,26 ****
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS
/* add your favourite output format here ... */
};
--- 20,27 ----
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS,
! PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..82653f7
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3791,3797 ****
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3791,3797 ----
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index e87b82b..b37c62e
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2125,2127 ****
--- 2125,2333 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^|Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^|Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^|Record 1
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 2
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 3
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 4
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 5
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 6
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 7
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 8
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 9
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ 2+^|Record 10
+ <| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <|0123456789 <|11
+ <|int >|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On Sun, Mar 22, 2015 at 10:09 AM, Bruce Momjian <bruce@momjian.us> wrote:
On Sat, Mar 21, 2015 at 09:20:03PM +0900, Michael Paquier wrote:
This does not work:
=# create table "5 2.2+^.^" ();
CREATE TABLE
=# \pset format asciidoc
Output format is asciidoc.
=# \d.List of relations
[options="header",cols="<l,<l,<l,<l",frame="none"]
|====
^l|Schema ^l|Name ^l|Type ^l|Owner
|public|5 2.2+^.^|table|ioltas
|====....
(1 row)
....I think that we should really put additional spaces on the left side
of the column separators "|". For example, this line:
|public|5 2.2+^.^|table|ioltas
should become that:
|public |5 2.2+^.^ |table |ioltas
And there is no problem.I have updated the attached patch to do as you suggested. Please also
test the \x output. Thanks.
Indeed. If I use a specific column name like this one, I am seeing
problems with the expanded mode:
=# create table "5 2.2+^.^" ("5 2.2+^.^" int);
CREATE TABLE
=# \x
Expanded display is on.
=# INSERT INTO "5 2.2+^.^" VALUES (1);
INSERT 0 1
=# table "5 2.2+^.^";
[cols="h,l",frame="none"]
|====
2+^|Record 1
<|5 2.2+^.^ >|1
|====
In this case the record is printed like that:
5 2.2+.
While it should show up like that:
5 2.2+^.^
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sun, Mar 22, 2015 at 08:06:17PM +0900, Michael Paquier wrote:
I have updated the attached patch to do as you suggested. Please also
test the \x output. Thanks.Indeed. If I use a specific column name like this one, I am seeing
problems with the expanded mode:
=# create table "5 2.2+^.^" ("5 2.2+^.^" int);
CREATE TABLE
=# \x
Expanded display is on.
=# INSERT INTO "5 2.2+^.^" VALUES (1);
INSERT 0 1
=# table "5 2.2+^.^";[cols="h,l",frame="none"]
|====
2+^|Record 1
<|5 2.2+^.^ >|1
|====In this case the record is printed like that:
5 2.2+.
While it should show up like that:
5 2.2+^.^
OK, fixed. It turns out you need to specify the style on each output
row ('l'/literal) so that a later data value of ^.^ is not intepreted as
a horizontal/vertial alignment specification. (Wow, it sounds like I
know what I am talking about. ;-) )
The new output is:
test=> \pset format asciidoc
Output format is asciidoc.
test=> \x
Expanded display is on.
test=> table "5 2.2+^.^";
[cols="h,l",frame="none"]
|====
2+^|Record 1
--> <l|5 2.2+^.^ >|1
|====
Notice the added 'l' next to the '<'. Updated patch attached. Any
other issues?
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a637001..82a91ec
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2092,2099 ****
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>, or
! <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
--- 2092,2099 ----
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>,
! <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
*************** lo_import 152801
*** 2120,2126 ****
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
--- 2120,2127 ----
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, <literal>troff-ms</>,
! and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 7c9f28d..a96f0ef
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2257,2262 ****
--- 2257,2265 ----
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
*************** do_pset(const char *param, const char *v
*** 2330,2338 ****
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2333,2343 ----
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index ac0dc27..93a517e
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index ce0d05d..266ed73
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_troff_ms_vertical(const printTable
*** 2476,2481 ****
--- 2476,2704 ----
}
}
+ /*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ if (i != 0)
+ fputs(" ", fout);
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if (((*ptr)[strspn(*ptr, " \t")] == '\0'))
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ {
+ fputs(" ", fout);
+ continue;
+ }
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2|\n", fout);
+ }
+
+ fputs("<l|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">" : "<");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
/********************************/
/* Public functions */
*************** printTable(const printTableContent *cont
*** 2873,2878 ****
--- 3096,3107 ----
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
*************** strlen_max_width(unsigned char *str, int
*** 3101,3103 ****
--- 3330,3334 ----
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index a1a89d0..a7eff99
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 20,26 ****
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS
/* add your favourite output format here ... */
};
--- 20,27 ----
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS,
! PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..82653f7
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3791,3797 ****
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3791,3797 ----
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index e87b82b..754606c
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2125,2127 ****
--- 2125,2333 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <|11
+ <l|int >|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On Tue, Mar 24, 2015 at 8:44 AM, Bruce Momjian wrote:
Notice the added 'l' next to the '<'. Updated patch attached. Any
other issues?
Ah, right. That's a good catch and your patch fixes the issue. Still,
there are problems with the tuple-only mode and the expanded mode. For
example using this example (wanted over-complicated):
create table "5 2.2+^.^" ("5 2.2+^.^" text, "4 2.2+^.^" text);
insert into "5 2.2+^.^" values ('5 2.2+^.^', '4 2.2+^.^');
insert into "5 2.2+^.^" values ('2 2.2+^.^', '3 2.2+^.^');
\pset format asciidoc
-- This prints first tuple as a header (which transforms "^.^" to "."
btw), 2nd as a normal row:
=# table "5 2.2+^.^" ;
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====
Time: 0.451 ms
And with the expanded mode this has an incorrect format:
=# \x
Expanded display is on.
=# table "5 2.2+^.^" ;
[cols="h,l",frame="none"]
|====
2|
<l|5 2.2+^.^ <|5 2.2+^.^
<l|4 2.2+^.^ <|4 2.2+^.^
2|
<l|5 2.2+^.^ <|2 2.2+^.^
<l|4 2.2+^.^ <|3 2.2+^.^
|====
Time: 0.555 ms
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Mar 24, 2015 at 11:15:33AM +0900, Michael Paquier wrote:
On Tue, Mar 24, 2015 at 8:44 AM, Bruce Momjian wrote:
Notice the added 'l' next to the '<'. Updated patch attached. Any
other issues?Ah, right. That's a good catch and your patch fixes the issue. Still,
there are problems with the tuple-only mode and the expanded mode. For
example using this example (wanted over-complicated):
create table "5 2.2+^.^" ("5 2.2+^.^" text, "4 2.2+^.^" text);
insert into "5 2.2+^.^" values ('5 2.2+^.^', '4 2.2+^.^');
insert into "5 2.2+^.^" values ('2 2.2+^.^', '3 2.2+^.^');
\pset format asciidoc
OK, all fixed. Some of the bugs were original, but at least one was
introduced by me. Patch attached. New output:
---------------------------------------------------------------------------
test=> \pset format asciidoc
Output format is asciidoc.
test=> table "5 2.2+^.^" ;
[options="header",cols="<l,<l",frame="none"]
|====
^l|5 2.2+^.^ ^l|4 2.2+^.^
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====
....
(2 rows)
....
test=> \x
Expanded display is on.
test=> table "5 2.2+^.^" ;
[cols="h,l",frame="none"]
|====
2+^|Record 1
<l|5 2.2+^.^ <l|5 2.2+^.^
<l|4 2.2+^.^ <l|4 2.2+^.^
2+^|Record 2
<l|5 2.2+^.^ <l|2 2.2+^.^
<l|4 2.2+^.^ <l|3 2.2+^.^
|====
test=> \x
Expanded display is off.
test=> \t
Tuples only is on.
test=> table "5 2.2+^.^" ;
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====
test=> \x
Expanded display is on.
test=> table "5 2.2+^.^" ;
[cols="h,l",frame="none"]
|====
2+|
<l|5 2.2+^.^ <l|5 2.2+^.^
<l|4 2.2+^.^ <l|4 2.2+^.^
2+|
<l|5 2.2+^.^ <l|2 2.2+^.^
<l|4 2.2+^.^ <l|3 2.2+^.^
|====
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a637001..82a91ec
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2092,2099 ****
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>, or
! <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
--- 2092,2099 ----
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>,
! <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
*************** lo_import 152801
*** 2120,2126 ****
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
--- 2120,2127 ----
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, <literal>troff-ms</>,
! and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 7c9f28d..a96f0ef
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2257,2262 ****
--- 2257,2265 ----
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
*************** do_pset(const char *param, const char *v
*** 2330,2338 ****
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2333,2343 ----
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index ac0dc27..93a517e
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index ce0d05d..4a72bf0
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_troff_ms_vertical(const printTable
*** 2476,2481 ****
--- 2476,2701 ----
}
}
+ /*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[options=\"header\",cols=\"", fout);
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ if (i % cont->ncolumns != 0)
+ fputs(" ", fout);
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ fputs(" ", fout);
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2+|\n", fout);
+ }
+
+ fputs("<l|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
/********************************/
/* Public functions */
*************** printTable(const printTableContent *cont
*** 2873,2878 ****
--- 3093,3104 ----
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
*************** strlen_max_width(unsigned char *str, int
*** 3101,3103 ****
--- 3327,3331 ----
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index a1a89d0..a7eff99
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 20,26 ****
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS
/* add your favourite output format here ... */
};
--- 20,27 ----
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS,
! PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..82653f7
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3791,3797 ****
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3791,3797 ----
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index e87b82b..7963ee5
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2125,2127 ****
--- 2125,2333 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On Wed, Mar 25, 2015 at 4:52 AM, Bruce Momjian <bruce@momjian.us> wrote:
On Tue, Mar 24, 2015 at 11:15:33AM +0900, Michael Paquier wrote:
On Tue, Mar 24, 2015 at 8:44 AM, Bruce Momjian wrote:
Notice the added 'l' next to the '<'. Updated patch attached. Any
other issues?Ah, right. That's a good catch and your patch fixes the issue. Still,
there are problems with the tuple-only mode and the expanded mode. For
example using this example (wanted over-complicated):
create table "5 2.2+^.^" ("5 2.2+^.^" text, "4 2.2+^.^" text);
insert into "5 2.2+^.^" values ('5 2.2+^.^', '4 2.2+^.^');
insert into "5 2.2+^.^" values ('2 2.2+^.^', '3 2.2+^.^');
\pset format asciidocOK, all fixed. Some of the bugs were original, but at least one was
introduced by me. Patch attached. New output:
test=> \x
Expanded display is off.
test=> \t
Tuples only is on.
test=> table "5 2.2+^.^" ;[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====
Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Mar 25, 2015 at 02:18:58PM +0900, Michael Paquier wrote:
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,
OK, fixed. Thanks for the testing. Patch attached. New output:
---------------------------------------------------------------------------
test=> \pset format asciidoc
Output format is asciidoc.
test=> \t
Tuples only is on.
test=> table "5 2.2+^.^" ;
[cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a637001..82a91ec
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2092,2099 ****
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>, or
! <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
--- 2092,2099 ----
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
! <literal>latex-longtable</literal>,
! <literal>troff-ms</literal>, or <literal>asciidoc</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
</para>
*************** lo_import 152801
*** 2120,2126 ****
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
--- 2120,2127 ----
<para>
The <literal>html</>, <literal>latex</>,
! <literal>latex-longtable</literal>, <literal>troff-ms</>,
! and <literal>asciidoc</>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 7c9f28d..a96f0ef
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2257,2262 ****
--- 2257,2265 ----
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
}
return "unknown";
}
*************** do_pset(const char *param, const char *v
*** 2330,2338 ****
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2333,2343 ----
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms, asciidoc\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index ac0dc27..93a517e
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, asciidoc ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index 40e5098..c3f317e
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_troff_ms_vertical(const printTable
*** 2487,2492 ****
--- 2487,2712 ----
}
}
+ /*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ if (i % cont->ncolumns != 0)
+ fputs(" ", fout);
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ fputs(" ", fout);
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2+|\n", fout);
+ }
+
+ fputs("<l|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
/********************************/
/* Public functions */
*************** printTable(const printTableContent *cont
*** 2884,2889 ****
--- 3104,3115 ----
else
print_troff_ms_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
*************** strlen_max_width(unsigned char *str, int
*** 3112,3114 ****
--- 3338,3342 ----
return str - start;
}
+
+
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index a1a89d0..a7eff99
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 20,26 ****
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS
/* add your favourite output format here ... */
};
--- 20,27 ----
PRINT_HTML,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
! PRINT_TROFF_MS,
! PRINT_ASCIIDOC
/* add your favourite output format here ... */
};
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..82653f7
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3791,3797 ****
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3791,3797 ----
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", "asciidoc", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index e87b82b..7963ee5
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2125,2127 ****
--- 2125,2333 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On Wed, Mar 25, 2015 at 4:59 PM, Bruce Momjian <bruce@momjian.us> wrote:
On Wed, Mar 25, 2015 at 02:18:58PM +0900, Michael Paquier wrote:
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,OK, fixed. Thanks for the testing. Patch attached. New output:
This time things look good from my side. I have played with this patch
some time, testing some crazy scenarios and I have not found problems.
That's cool stuff, thanks!
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Mar 25, 2015 at 09:37:08PM +0900, Michael Paquier wrote:
On Wed, Mar 25, 2015 at 4:59 PM, Bruce Momjian <bruce@momjian.us> wrote:
On Wed, Mar 25, 2015 at 02:18:58PM +0900, Michael Paquier wrote:
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,OK, fixed. Thanks for the testing. Patch attached. New output:
This time things look good from my side. I have played with this patch
some time, testing some crazy scenarios and I have not found problems.
That's cool stuff, thanks!
Wow, thanks. I never would have gotten here without your help.
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Mar 25, 2015 at 09:12:41AM -0400, Bruce Momjian wrote:
On Wed, Mar 25, 2015 at 09:37:08PM +0900, Michael Paquier wrote:
On Wed, Mar 25, 2015 at 4:59 PM, Bruce Momjian <bruce@momjian.us> wrote:
On Wed, Mar 25, 2015 at 02:18:58PM +0900, Michael Paquier wrote:
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,OK, fixed. Thanks for the testing. Patch attached. New output:
This time things look good from my side. I have played with this patch
some time, testing some crazy scenarios and I have not found problems.
That's cool stuff, thanks!Wow, thanks. I never would have gotten here without your help.
Slightly updated patch attached and applied. I moved asciidoc after
HTML in the list, rather than at the end. Thanks for everyone's hard
work on this.
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
Attachments:
asciidoc.difftext/x-diff; charset=us-asciiDownload
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index a33e460..1f29615
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** lo_import 152801
*** 2090,2096 ****
<para>
Sets the output format to one of <literal>unaligned</literal>,
<literal>aligned</literal>, <literal>wrapped</literal>,
! <literal>html</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
<literal>latex-longtable</literal>, or
<literal>troff-ms</literal>.
--- 2090,2096 ----
<para>
Sets the output format to one of <literal>unaligned</literal>,
<literal>aligned</literal>, <literal>wrapped</literal>,
! <literal>html</literal>, <literal>asciidoc</literal>,
<literal>latex</literal> (uses <literal>tabular</literal>),
<literal>latex-longtable</literal>, or
<literal>troff-ms</literal>.
*************** lo_import 152801
*** 2119,2125 ****
</para>
<para>
! The <literal>html</>, <literal>latex</>,
<literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
--- 2119,2125 ----
</para>
<para>
! The <literal>html</>, <literal>asciidoc</>, <literal>latex</>,
<literal>latex-longtable</literal>, and <literal>troff-ms</>
formats put out tables that are intended to
be included in documents using the respective mark-up
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index e64c033..916f1c6
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** _align2string(enum printFormat in)
*** 2249,2254 ****
--- 2249,2257 ----
case PRINT_HTML:
return "html";
break;
+ case PRINT_ASCIIDOC:
+ return "asciidoc";
+ break;
case PRINT_LATEX:
return "latex";
break;
*************** do_pset(const char *param, const char *v
*** 2325,2330 ****
--- 2328,2335 ----
popt->topt.format = PRINT_WRAPPED;
else if (pg_strncasecmp("html", value, vallen) == 0)
popt->topt.format = PRINT_HTML;
+ else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
+ popt->topt.format = PRINT_ASCIIDOC;
else if (pg_strncasecmp("latex", value, vallen) == 0)
popt->topt.format = PRINT_LATEX;
else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
*************** do_pset(const char *param, const char *v
*** 2333,2339 ****
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
return false;
}
--- 2338,2344 ----
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, troff-ms\n");
return false;
}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index 2da444b..f58f5e5
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** helpVariables(unsigned short int pager)
*** 351,357 ****
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, latex, ..]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
--- 351,357 ----
fprintf(output, _(" expanded (or x) toggle expanded output\n"));
fprintf(output, _(" fieldsep field separator for unaligned output (default '|')\n"));
fprintf(output, _(" fieldsep_zero set field separator in unaligned mode to zero\n"));
! fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
new file mode 100644
index 9c12dbe..e97b563
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
*************** print_html_vertical(const printTableCont
*** 1879,1884 ****
--- 1879,2105 ----
/*************************/
+ /* ASCIIDOC */
+ /*************************/
+
+ static void
+ asciidoc_escaped_print(const char *in, FILE *fout)
+ {
+ const char *p;
+ for (p = in; *p; p++)
+ {
+ switch(*p)
+ {
+ case '|':
+ fputs("\\|", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_text(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
+ for(i = 0; i < cont->ncolumns; i++)
+ {
+ if (i != 0)
+ fputs(",", fout);
+ fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
+ }
+ fputs("\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+
+ /* print headers */
+ if (!opt_tuples_only)
+ {
+ for (ptr = cont->headers; *ptr; ptr++)
+ {
+ if (ptr != cont->headers)
+ fputs(" ", fout);
+ fputs("^l|", fout);
+ asciidoc_escaped_print(*ptr, fout);
+ }
+ fputs("\n", fout);
+ }
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ }
+
+ if (i % cont->ncolumns != 0)
+ fputs(" ", fout);
+ fputs("|", fout);
+
+ /* protect against needless spaces */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ {
+ if ((i + 1) % cont->ncolumns != 0)
+ fputs(" ", fout);
+ }
+ else
+ asciidoc_escaped_print(*ptr, fout);
+
+ if ((i + 1) % cont->ncolumns == 0)
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ printTableFooter *footers = footers_with_default(cont);
+
+ /* print footers */
+ if (!opt_tuples_only && footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ static void
+ print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
+ {
+ bool opt_tuples_only = cont->opt->tuples_only;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
+ unsigned int i;
+ const char *const * ptr;
+
+ if (cancel_pressed)
+ return;
+
+ if (cont->opt->start_table)
+ {
+ /* print table in new paragraph - enforce preliminary new line */
+ fputs("\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && cont->title)
+ {
+ fputs(".", fout);
+ fputs(cont->title, fout);
+ fputs("\n", fout);
+ }
+
+ /* print table [] header definition */
+ fputs("[cols=\"h,l\"", fout);
+ switch (opt_border)
+ {
+ case 0:
+ fputs(",frame=\"none\",grid=\"none\"", fout);
+ break;
+ case 1:
+ fputs(",frame=\"none\"", fout);
+ break;
+ case 2:
+ fputs(",frame=\"all\",grid=\"all\"", fout);
+ break;
+ }
+ fputs("]\n", fout);
+ fputs("|====\n", fout);
+ }
+
+ /* print records */
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
+ {
+ if (i % cont->ncolumns == 0)
+ {
+ if (cancel_pressed)
+ break;
+ if (!opt_tuples_only)
+ fprintf(fout,
+ "2+^|Record %lu\n",
+ record++);
+ else
+ fputs("2+|\n", fout);
+ }
+
+ fputs("<l|", fout);
+ asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
+
+ fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
+ /* is string only whitespace? */
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0')
+ fputs(" ", fout);
+ else
+ asciidoc_escaped_print(*ptr, fout);
+ fputs("\n", fout);
+ }
+
+ fputs("|====\n", fout);
+
+ if (cont->opt->stop_table)
+ {
+ /* print footers */
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ fputs("\n....\n", fout);
+ for (f = cont->footers; f; f = f->next)
+ {
+ fputs(f->data, fout);
+ fputs("\n", fout);
+ }
+ fputs("....\n", fout);
+ }
+ }
+ }
+
+ /*************************/
/* LaTeX */
/*************************/
*************** printTable(const printTableContent *cont
*** 2872,2877 ****
--- 3093,3104 ----
else
print_html_text(cont, fout);
break;
+ case PRINT_ASCIIDOC:
+ if (cont->opt->expanded == 1)
+ print_asciidoc_vertical(cont, fout);
+ else
+ print_asciidoc_text(cont, fout);
+ break;
case PRINT_LATEX:
if (cont->opt->expanded == 1)
print_latex_vertical(cont, fout);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
new file mode 100644
index 66cdaf3..322db4d
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
*************** enum printFormat
*** 18,23 ****
--- 18,24 ----
PRINT_ALIGNED,
PRINT_WRAPPED,
PRINT_HTML,
+ PRINT_ASCIIDOC,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
PRINT_TROFF_MS
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
new file mode 100644
index e39a07c..dfcb66b
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** psql_completion(const char *text, int st
*** 3790,3797 ****
if (strcmp(prev_wd, "format") == 0)
{
static const char *const my_list[] =
! {"unaligned", "aligned", "wrapped", "html", "latex",
! "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
--- 3790,3797 ----
if (strcmp(prev_wd, "format") == 0)
{
static const char *const my_list[] =
! {"unaligned", "aligned", "wrapped", "html", "asciidoc",
! "latex", "latex-longtable", "troff-ms", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
new file mode 100644
index a2a2615..6ff9be1
*** a/src/test/regress/expected/psql.out
--- b/src/test/regress/expected/psql.out
*************** execute q;
*** 2126,2128 ****
--- 2126,2334 ----
+------------------+-------------------+
deallocate q;
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none",grid="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 1
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="none"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset border 2
+ execute q;
+
+ [options="header",cols="<l,<l,>l",frame="all",grid="all"]
+ |====
+ ^l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ ^l|0123456789 ^l|int
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ | \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (& |11 |11
+ |====
+
+ ....
+ (10 rows)
+ ....
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ [cols="h,l",frame="none",grid="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 1
+ execute q;
+
+ [cols="h,l",frame="none"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ \pset border 2
+ execute q;
+
+ [cols="h,l",frame="all",grid="all"]
+ |====
+ 2+^|Record 1
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 2
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 3
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 4
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 5
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 6
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 7
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 8
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 9
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ 2+^|Record 10
+ <l| \| -- \| 012345678 9abc def!*@#&!@(*&*~~_+-=\ \ <l| \| = \| lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&
+ <l|0123456789 <l|11
+ <l|int >l|11
+ |====
+ deallocate q;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
new file mode 100644
index 5ccc68f..fa1df8b
*** a/src/test/regress/sql/psql.sql
--- b/src/test/regress/sql/psql.sql
*************** execute q;
*** 276,278 ****
--- 276,303 ----
execute q;
deallocate q;
+
+ prepare q as select ' | = | lkjsafi\\/ /oeu rio)(!@&*#)*(!&@*) \ (&' as " | -- | 012345678 9abc def!*@#&!@(*&*~~_+-=\ \", '11' as "0123456789", 11 as int from generate_series(1,10) as n;
+
+ \pset format asciidoc
+ \pset expanded off
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ \pset expanded on
+ \pset border 0
+ execute q;
+
+ \pset border 1
+ execute q;
+
+ \pset border 2
+ execute q;
+
+ deallocate q;
On 31 March 2015 at 16:35, Bruce Momjian <bruce@momjian.us> wrote:
On Wed, Mar 25, 2015 at 09:12:41AM -0400, Bruce Momjian wrote:
On Wed, Mar 25, 2015 at 09:37:08PM +0900, Michael Paquier wrote:
On Wed, Mar 25, 2015 at 4:59 PM, Bruce Momjian <bruce@momjian.us>
wrote:
On Wed, Mar 25, 2015 at 02:18:58PM +0900, Michael Paquier wrote:
[options="header",cols="<l,<l",frame="none"]
|====
|5 2.2+^.^ |4 2.2+^.^
|2 2.2+^.^ |3 2.2+^.^
|====Hm. This is still incorrect. You should remove options="header" here
or the first tuple is treated as a header in the case
non-expanded/tuple-only. Your patch removes correctly the header for
the expanded/tuple-only case though.
Regards,OK, fixed. Thanks for the testing. Patch attached. New output:
This time things look good from my side. I have played with this patch
some time, testing some crazy scenarios and I have not found problems.
That's cool stuff, thanks!Wow, thanks. I never would have gotten here without your help.
Slightly updated patch attached and applied. I moved asciidoc after
HTML in the list, rather than at the end. Thanks for everyone's hard
work on this.
I think I done gone broke it:
CREATE TABLE "| 3^.||moo|hello," (stuff int, "|&.^hje||" text);
INSERT INTO "| 3^.||moo|hello," VALUES (2,'hello');
Output:
[options="header",cols=">l,<l",frame="none"]
|====
^l|stuff ^l|\|&.^hje\|\|
|2 |hello
|====
....
(1 row)
....
This results in:
<table class="tableblock frame-none grid-all spread">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-center valign-top">stuff</th>
<th class="tableblock halign-center valign-top">|&.^hje||2</th>
</tr>
</thead>
</table>
Using asciidoctor 1.5.2.
--
Thom
On Tue, Mar 31, 2015 at 05:25:48PM +0100, Thom Brown wrote:
Slightly updated patch attached and applied.� I moved asciidoc after
HTML in the list, rather than at the end.� Thanks for everyone's hard
work on this.�I think I done gone broke it:
CREATE TABLE "| 3^.||moo|hello," (stuff int, "|&.^hje||" text);
INSERT INTO "| 3^.||moo|hello," VALUES (2,'hello');
Output:
[options="header",cols=">l,<l",frame="none"]
|====
^l|stuff ^l|\|&.^hje\|\|
|2 |hello
|====
Uh, you broke asciidoctor 1.5.2. ;-) LOL
I installed the Asciidoctor Firefox plugin:
https://addons.mozilla.org/en-US/firefox/addon/asciidoctorjs-live-preview/
and was able to see that asciidoctor sucks in the next row's first cell value
when the _heading_ ends with an escaped pipe, e.g. this:
[options="header",cols=">l,<l",frame="none"]
|====
^l|stuff ^l|abc\|X
|2 |hello\|
|3 |hello
|====
yields a correct HTML heading of:
stuff abc|X
which is good, but if you remove the "X" from the asciidoc heading, the
HTML output heading is:
stuff abc|2
The "X" is gone, but the "2" from the first data row is now in the
heading, and the first and only data row is now:
hello|3 hello
I can't add a trailing pipe to the header line because it breaks output
in https://asciidoclive.com/ .
I have reported this on the asciidoc discussion list:
http://discuss.asciidoctor.org/Problem-with-table-heading-ending-in-a-pipe-td2902.html
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Mar 31, 2015 at 05:06:49PM -0400, Bruce Momjian wrote:
Uh, you broke asciidoctor 1.5.2. ;-) LOL
I installed the Asciidoctor Firefox plugin:
Asciidoctor has confirmed they have a bug and hope to fix it in their
next release:
http://discuss.asciidoctor.org/Problem-with-table-heading-ending-in-a-pipe-tp2902p2916.html
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers