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
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);
 		}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to