Add psql expanded auto mode

This adds the "auto" option to the \x command, which switches to the
expanded mode when the normal output would be wider than the screen.

reviewed by Noah Misch
This commit is contained in:
Peter Eisentraut 2011-11-12 17:03:10 +02:00
parent aa3299f256
commit 95d2af1646
5 changed files with 73 additions and 37 deletions

View File

@ -1860,7 +1860,8 @@ lo_import 152801
<para> <para>
Sets the target width for the <literal>wrapped</> format, and also Sets the target width for the <literal>wrapped</> format, and also
the width limit for determining whether output is wide enough to the width limit for determining whether output is wide enough to
require the pager. require the pager or switch to the vertical display in expanded auto
mode.
Zero (the default) causes the target width to be controlled by the Zero (the default) causes the target width to be controlled by the
environment variable <envar>COLUMNS</>, or the detected screen width environment variable <envar>COLUMNS</>, or the detected screen width
if <envar>COLUMNS</> is not set. if <envar>COLUMNS</> is not set.
@ -1876,15 +1877,19 @@ lo_import 152801
<term><literal>expanded</literal> (or <literal>x</literal>)</term> <term><literal>expanded</literal> (or <literal>x</literal>)</term>
<listitem> <listitem>
<para> <para>
If <replaceable class="parameter">value</replaceable> is specified If <replaceable class="parameter">value</replaceable> is specified it
it must be either <literal>on</literal> or <literal>off</literal> must be either <literal>on</literal> or <literal>off</literal>, which
which will enable or disable expanded mode. If <replaceable will enable or disable expanded mode, or <literal>auto</literal>.
class="parameter">value</replaceable> is omitted the command toggles If <replaceable class="parameter">value</replaceable> is omitted the
between regular and expanded mode. command toggles between the on and off settings. When expanded mode
When expanded mode is enabled, query results is enabled, query results are displayed in two columns, with the
are displayed in two columns, with the column name on the left and column name on the left and the data on the right. This mode is
the data on the right. This mode is useful if the data wouldn't fit useful if the data wouldn't fit on the screen in the
on the screen in the normal <quote>horizontal</quote> mode. normal <quote>horizontal</quote> mode. In the auto setting, the
expanded mode is used whenever the query output is wider than the
screen, otherwise the regular mode is used. The auto setting is only
effective in the aligned and wrapped formats. In other formats, it
always behaves as if the expanded mode is off.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -2326,10 +2331,10 @@ lo_import 152801
<varlistentry> <varlistentry>
<term><literal>\x</literal></term> <term><literal>\x [ <replaceable class="parameter">on</replaceable> | <replaceable class="parameter">off</replaceable> | <replaceable class="parameter">auto</replaceable> ]</literal></term>
<listitem> <listitem>
<para> <para>
Toggles expanded table formatting mode. As such it is equivalent to Sets or toggles expanded table formatting mode. As such it is equivalent to
<literal>\pset expanded</literal>. <literal>\pset expanded</literal>.
</para> </para>
</listitem> </listitem>
@ -3197,7 +3202,8 @@ $endif
<para> <para>
If <literal>\pset columns</> is zero, controls the If <literal>\pset columns</> is zero, controls the
width for the <literal>wrapped</> format and width for determining width for the <literal>wrapped</> format and width for determining
if wide output requires the pager. if wide output requires the pager or should be switched to the
vertical format in expanded auto mode.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -1355,7 +1355,7 @@ exec_command(const char *cmd,
free(fname); free(fname);
} }
/* \x -- toggle expanded table representation */ /* \x -- set or toggle expanded table representation */
else if (strcmp(cmd, "x") == 0) else if (strcmp(cmd, "x") == 0)
{ {
char *opt = psql_scan_slash_option(scan_state, char *opt = psql_scan_slash_option(scan_state,
@ -2189,14 +2189,21 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
/* set expanded/vertical mode */ /* set expanded/vertical mode */
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0) else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
{ {
if (value) if (value && pg_strcasecmp(value, "auto") == 0)
popt->topt.expanded = 2;
else if (value)
popt->topt.expanded = ParseVariableBool(value); popt->topt.expanded = ParseVariableBool(value);
else else
popt->topt.expanded = !popt->topt.expanded; popt->topt.expanded = !popt->topt.expanded;
if (!quiet) if (!quiet)
printf(popt->topt.expanded {
? _("Expanded display is on.\n") if (popt->topt.expanded == 1)
: _("Expanded display is off.\n")); printf(_("Expanded display is on.\n"));
else if (popt->topt.expanded == 2)
printf(_("Expanded display is used automatically.\n"));
else
printf(_("Expanded display is off.\n"));
}
} }
/* locale-aware numeric output */ /* locale-aware numeric output */
@ -2356,7 +2363,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.columns = atoi(value); popt->topt.columns = atoi(value);
if (!quiet) if (!quiet)
printf(_("Target width for \"wrapped\" format is %d.\n"), popt->topt.columns); printf(_("Target width is %d.\n"), popt->topt.columns);
} }
else else

View File

@ -242,8 +242,8 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"), fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"),
ON(pset.popt.topt.tuples_only)); ON(pset.popt.topt.tuples_only));
fprintf(output, _(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n")); fprintf(output, _(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n"));
fprintf(output, _(" \\x [on|off] toggle expanded output (currently %s)\n"), fprintf(output, _(" \\x [on|off|auto] toggle expanded output (currently %s)\n"),
ON(pset.popt.topt.expanded)); pset.popt.topt.expanded == 2 ? "auto" : ON(pset.popt.topt.expanded));
fprintf(output, "\n"); fprintf(output, "\n");
fprintf(output, _("Connection\n")); fprintf(output, _("Connection\n"));

View File

@ -122,9 +122,11 @@ const printTextFormat pg_utf8format =
/* Local functions */ /* Local functions */
static int strlen_max_width(unsigned char *str, int *target_width, int encoding); static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines, static void IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded,
FILE **fout, bool *is_pager); FILE **fout, bool *is_pager);
static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
static void * static void *
pg_local_malloc(size_t size) pg_local_malloc(size_t size)
@ -713,6 +715,17 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
} }
} }
/*
* If in expanded auto mode, we have now calculated the expected width, so
* we can now escape to vertical mode if necessary.
*/
if (cont->opt->expanded == 2 && output_columns > 0 &&
(output_columns < total_header_width || output_columns < width_total))
{
print_aligned_vertical(cont, fout);
return;
}
/* If we wrapped beyond the display width, use the pager */ /* If we wrapped beyond the display width, use the pager */
if (!is_pager && fout == stdout && output_columns > 0 && if (!is_pager && fout == stdout && output_columns > 0 &&
(output_columns < total_header_width || output_columns < width_total)) (output_columns < total_header_width || output_columns < width_total))
@ -756,7 +769,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
extra_row_output_lines = 0; extra_row_output_lines = 0;
} }
} }
IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager); IsPagerNeeded(cont, extra_output_lines, false, &fout, &is_pager);
} }
/* time to output */ /* time to output */
@ -1125,6 +1138,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
dformatsize = 0; dformatsize = 0;
struct lineptr *hlineptr, struct lineptr *hlineptr,
*dlineptr; *dlineptr;
bool is_pager = false;
if (cancel_pressed) if (cancel_pressed)
return; return;
@ -1139,6 +1153,13 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
return; return;
} }
/*
* Deal with the pager here instead of in printTable(), because we could
* get here via print_aligned_text() in expanded auto mode, and so we have
* to recalcuate the pager requirement based on vertical output.
*/
IsPagerNeeded(cont, 0, true, &fout, &is_pager);
/* Find the maximum dimensions for the headers */ /* Find the maximum dimensions for the headers */
for (i = 0; i < cont->ncolumns; i++) for (i = 0; i < cont->ncolumns; i++)
{ {
@ -1295,6 +1316,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
free(dlineptr->ptr); free(dlineptr->ptr);
free(hlineptr); free(hlineptr);
free(dlineptr); free(dlineptr);
if (is_pager)
ClosePager(fout);
} }
@ -2265,14 +2289,14 @@ printTableCleanup(printTableContent *const content)
* Setup pager if required * Setup pager if required
*/ */
static void static void
IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout, IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded, FILE **fout,
bool *is_pager) bool *is_pager)
{ {
if (*fout == stdout) if (*fout == stdout)
{ {
int lines; int lines;
if (cont->opt->expanded) if (expanded)
lines = (cont->ncolumns + 1) * cont->nrows; lines = (cont->ncolumns + 1) * cont->nrows;
else else
lines = cont->nrows + 1; lines = cont->nrows + 1;
@ -2310,11 +2334,10 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
if (cont->opt->format == PRINT_NOTHING) if (cont->opt->format == PRINT_NOTHING)
return; return;
/* print_aligned_text() handles the pager itself */ /* print_aligned_*() handles the pager themselves */
if ((cont->opt->format != PRINT_ALIGNED && if (cont->opt->format != PRINT_ALIGNED &&
cont->opt->format != PRINT_WRAPPED) || cont->opt->format != PRINT_WRAPPED)
cont->opt->expanded) IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
IsPagerNeeded(cont, 0, &fout, &is_pager);
/* print the stuff */ /* print the stuff */
@ -2324,32 +2347,32 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
switch (cont->opt->format) switch (cont->opt->format)
{ {
case PRINT_UNALIGNED: case PRINT_UNALIGNED:
if (cont->opt->expanded) if (cont->opt->expanded == 1)
print_unaligned_vertical(cont, fout); print_unaligned_vertical(cont, fout);
else else
print_unaligned_text(cont, fout); print_unaligned_text(cont, fout);
break; break;
case PRINT_ALIGNED: case PRINT_ALIGNED:
case PRINT_WRAPPED: case PRINT_WRAPPED:
if (cont->opt->expanded) if (cont->opt->expanded == 1)
print_aligned_vertical(cont, fout); print_aligned_vertical(cont, fout);
else else
print_aligned_text(cont, fout); print_aligned_text(cont, fout);
break; break;
case PRINT_HTML: case PRINT_HTML:
if (cont->opt->expanded) if (cont->opt->expanded == 1)
print_html_vertical(cont, fout); print_html_vertical(cont, fout);
else else
print_html_text(cont, fout); print_html_text(cont, fout);
break; break;
case PRINT_LATEX: case PRINT_LATEX:
if (cont->opt->expanded) if (cont->opt->expanded == 1)
print_latex_vertical(cont, fout); print_latex_vertical(cont, fout);
else else
print_latex_text(cont, fout); print_latex_text(cont, fout);
break; break;
case PRINT_TROFF_MS: case PRINT_TROFF_MS:
if (cont->opt->expanded) if (cont->opt->expanded == 1)
print_troff_ms_vertical(cont, fout); print_troff_ms_vertical(cont, fout);
else else
print_troff_ms_text(cont, fout); print_troff_ms_text(cont, fout);

View File

@ -70,8 +70,8 @@ typedef struct printTextFormat
typedef struct printTableOpt typedef struct printTableOpt
{ {
enum printFormat format; /* see enum above */ enum printFormat format; /* see enum above */
bool expanded; /* expanded/vertical output (if supported by unsigned short int expanded;/* expanded/vertical output (if supported by
* output format) */ * output format); 0=no, 1=yes, 2=auto */
unsigned short int border; /* Print a border around the table. 0=none, unsigned short int border; /* Print a border around the table. 0=none,
* 1=dividing lines, 2=full */ * 1=dividing lines, 2=full */
unsigned short int pager; /* use pager for output (if to stdout and unsigned short int pager; /* use pager for output (if to stdout and