Add detection of psql pager to trigger on wide output. Also add pager
detection for wrapped lines or lines with newlines that need pager to display.
This commit is contained in:
parent
e6dbcb72fa
commit
43ee22826b
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.204 2008/05/14 04:07:01 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.205 2008/05/16 16:59:05 momjian Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -1555,7 +1555,8 @@ lo_import 152801
|
||||
<term><literal>columns</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Controls the target width for the <literal>wrapped</> format.
|
||||
Controls the target width for the <literal>wrapped</> format,
|
||||
and width for determining if wide output requires the pager.
|
||||
Zero (the default) causes the <literal>wrapped</> format to
|
||||
affect only screen output.
|
||||
</para>
|
||||
@ -1717,10 +1718,9 @@ lo_import 152801
|
||||
When the pager is <literal>off</>, the pager is not used. When the pager
|
||||
is <literal>on</>, the pager is used only when appropriate, i.e. the
|
||||
output is to a terminal and will not fit on the screen.
|
||||
(<application>psql</> does not do a perfect job of estimating
|
||||
when to use the pager.) <literal>\pset pager</> turns the
|
||||
pager on and off. Pager can also be set to <literal>always</>,
|
||||
which causes the pager to be always used.
|
||||
<literal>\pset pager</> turns the pager on and off. Pager can
|
||||
also be set to <literal>always</>, which causes the pager to be
|
||||
always used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -2734,8 +2734,9 @@ $endif
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Used for the <literal>wrapped</> output format if
|
||||
<literal>\pset columns</> is zero.
|
||||
If <literal>\pset columns</> is zero, controls the
|
||||
width for the <literal>wrapped</> format and width for determining
|
||||
if wide output requires the pager.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.101 2008/05/13 00:14:11 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.102 2008/05/16 16:59:05 momjian Exp $
|
||||
*/
|
||||
#include "postgres_fe.h"
|
||||
|
||||
@ -45,6 +45,8 @@ static char *thousands_sep;
|
||||
|
||||
/* Local functions */
|
||||
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
|
||||
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
|
||||
FILE **fout, bool *is_pager);
|
||||
|
||||
|
||||
static void *
|
||||
@ -394,7 +396,7 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
|
||||
* Print pretty boxes around cells.
|
||||
*/
|
||||
static void
|
||||
print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
{
|
||||
bool opt_tuples_only = cont->opt->tuples_only;
|
||||
bool opt_numeric_locale = cont->opt->numericLocale;
|
||||
@ -416,6 +418,8 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
unsigned char **format_buf;
|
||||
unsigned int width_total;
|
||||
unsigned int total_header_width;
|
||||
unsigned int extra_row_output_lines = 0;
|
||||
unsigned int extra_output_lines = 0;
|
||||
|
||||
const char * const *ptr;
|
||||
|
||||
@ -424,6 +428,7 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
bool *header_done; /* Have all header lines been output? */
|
||||
int *bytes_output; /* Bytes output for column value */
|
||||
int output_columns = 0; /* Width of interactive console */
|
||||
bool is_pager = false;
|
||||
|
||||
if (cancel_pressed)
|
||||
return;
|
||||
@ -476,9 +481,14 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
max_nl_lines[i] = nl_lines;
|
||||
if (bytes_required > max_bytes[i])
|
||||
max_bytes[i] = bytes_required;
|
||||
if (nl_lines > extra_row_output_lines)
|
||||
extra_row_output_lines = nl_lines;
|
||||
|
||||
width_header[i] = width;
|
||||
}
|
||||
/* Add height of tallest header column */
|
||||
extra_output_lines += extra_row_output_lines;
|
||||
extra_row_output_lines = 0;
|
||||
|
||||
/* scan all cells, find maximum width, compute cell_count */
|
||||
for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
|
||||
@ -487,7 +497,6 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
nl_lines,
|
||||
bytes_required;
|
||||
|
||||
/* Get width, ignore nl_lines */
|
||||
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
|
||||
&width, &nl_lines, &bytes_required);
|
||||
if (opt_numeric_locale && cont->aligns[i % col_count] == 'r')
|
||||
@ -552,28 +561,28 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
for (i = 0; i < col_count; i++)
|
||||
width_wrap[i] = max_width[i];
|
||||
|
||||
/*
|
||||
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
|
||||
*/
|
||||
if (cont->opt->columns > 0)
|
||||
output_columns = cont->opt->columns;
|
||||
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
|
||||
{
|
||||
if (cont->opt->env_columns > 0)
|
||||
output_columns = cont->opt->env_columns;
|
||||
#ifdef TIOCGWINSZ
|
||||
else
|
||||
{
|
||||
struct winsize screen_size;
|
||||
|
||||
if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
|
||||
output_columns = screen_size.ws_col;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cont->opt->format == PRINT_WRAPPED)
|
||||
{
|
||||
/*
|
||||
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
|
||||
*/
|
||||
if (cont->opt->columns > 0)
|
||||
output_columns = cont->opt->columns;
|
||||
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
|
||||
{
|
||||
if (cont->opt->env_columns > 0)
|
||||
output_columns = cont->opt->env_columns;
|
||||
#ifdef TIOCGWINSZ
|
||||
else
|
||||
{
|
||||
struct winsize screen_size;
|
||||
|
||||
if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
|
||||
output_columns = screen_size.ws_col;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Optional optimized word wrap. Shrink columns with a high max/avg
|
||||
* ratio. Slighly bias against wider columns. (Increases chance a
|
||||
@ -623,6 +632,49 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we wrapped beyond the display width, use the pager */
|
||||
if (!is_pager && output_columns > 0 &&
|
||||
(output_columns < total_header_width || output_columns < width_total))
|
||||
{
|
||||
fout = PageOutput(INT_MAX, cont->opt->pager); /* force pager */
|
||||
is_pager = true;
|
||||
}
|
||||
|
||||
/* Check if newlines or our wrapping now need the pager */
|
||||
if (!is_pager)
|
||||
{
|
||||
/* scan all cells, find maximum width, compute cell_count */
|
||||
for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
|
||||
{
|
||||
int width,
|
||||
nl_lines,
|
||||
bytes_required;
|
||||
|
||||
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
|
||||
&width, &nl_lines, &bytes_required);
|
||||
if (opt_numeric_locale && cont->align[i % col_count] == 'r')
|
||||
width += additional_numeric_locale_len(*ptr);
|
||||
|
||||
/*
|
||||
* A row can have both wrapping and newlines that cause
|
||||
* it to display across multiple lines. We check
|
||||
* for both cases below.
|
||||
*/
|
||||
if (width > 0 && width_wrap[i] &&
|
||||
(width-1) / width_wrap[i] + nl_lines > extra_row_output_lines)
|
||||
extra_row_output_lines = (width-1) / width_wrap[i] + nl_lines;
|
||||
|
||||
/* If last column, add tallest column height */
|
||||
if (i % col_count == col_count - 1)
|
||||
{
|
||||
/* Add height of tallest row */
|
||||
extra_output_lines += extra_row_output_lines;
|
||||
extra_row_output_lines = 0;
|
||||
}
|
||||
}
|
||||
IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager);
|
||||
}
|
||||
|
||||
/* time to output */
|
||||
if (cont->opt->start_table)
|
||||
{
|
||||
@ -882,6 +934,9 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
|
||||
for (i = 0; i < col_count; i++)
|
||||
free(format_buf[i]);
|
||||
free(format_buf);
|
||||
|
||||
if (is_pager)
|
||||
ClosePager(fout);
|
||||
}
|
||||
|
||||
|
||||
@ -2115,21 +2170,15 @@ printTableCleanup(printTableContent *content)
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this to print just any table in the supported formats.
|
||||
* IsPagerNeeded
|
||||
*
|
||||
* Setup pager if required
|
||||
*/
|
||||
void
|
||||
printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout,
|
||||
bool *is_pager)
|
||||
{
|
||||
FILE *output;
|
||||
bool is_pager = false;
|
||||
|
||||
if (cancel_pressed)
|
||||
return;
|
||||
|
||||
if (cont->opt->format == PRINT_NOTHING)
|
||||
return;
|
||||
|
||||
if (fout == stdout)
|
||||
if (*fout == stdout)
|
||||
{
|
||||
int lines;
|
||||
|
||||
@ -2150,58 +2199,79 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
lines++;
|
||||
}
|
||||
|
||||
output = PageOutput(lines, cont->opt->pager);
|
||||
is_pager = (output != fout);
|
||||
*fout = PageOutput(lines + extra_lines, cont->opt->pager);
|
||||
*is_pager = (*fout != stdout);
|
||||
}
|
||||
else
|
||||
output = fout;
|
||||
*is_pager = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this to print just any table in the supported formats.
|
||||
*/
|
||||
void
|
||||
printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
{
|
||||
bool is_pager = false;
|
||||
|
||||
if (cancel_pressed)
|
||||
return;
|
||||
|
||||
if (cont->opt->format == PRINT_NOTHING)
|
||||
return;
|
||||
|
||||
/* print_aligned_text() handles the pager itself */
|
||||
if ((cont->opt->format != PRINT_ALIGNED &&
|
||||
cont->opt->format != PRINT_WRAPPED) ||
|
||||
cont->opt->expanded)
|
||||
IsPagerNeeded(cont, 0, &fout, &is_pager);
|
||||
|
||||
/* print the stuff */
|
||||
|
||||
if (flog)
|
||||
print_aligned_text(cont, is_pager, flog);
|
||||
print_aligned_text(cont, flog);
|
||||
|
||||
switch (cont->opt->format)
|
||||
{
|
||||
case PRINT_UNALIGNED:
|
||||
if (cont->opt->expanded)
|
||||
print_unaligned_vertical(cont, output);
|
||||
print_unaligned_vertical(cont, fout);
|
||||
else
|
||||
print_unaligned_text(cont, output);
|
||||
print_unaligned_text(cont, fout);
|
||||
break;
|
||||
case PRINT_ALIGNED:
|
||||
case PRINT_WRAPPED:
|
||||
if (cont->opt->expanded)
|
||||
print_aligned_vertical(cont, output);
|
||||
print_aligned_vertical(cont, fout);
|
||||
else
|
||||
print_aligned_text(cont, is_pager, output);
|
||||
print_aligned_text(cont, fout);
|
||||
break;
|
||||
case PRINT_HTML:
|
||||
if (cont->opt->expanded)
|
||||
print_html_vertical(cont, output);
|
||||
print_html_vertical(cont, fout);
|
||||
else
|
||||
print_html_text(cont, output);
|
||||
print_html_text(cont, fout);
|
||||
break;
|
||||
case PRINT_LATEX:
|
||||
if (cont->opt->expanded)
|
||||
print_latex_vertical(cont, output);
|
||||
print_latex_vertical(cont, fout);
|
||||
else
|
||||
print_latex_text(cont, output);
|
||||
print_latex_text(cont, fout);
|
||||
break;
|
||||
case PRINT_TROFF_MS:
|
||||
if (cont->opt->expanded)
|
||||
print_troff_ms_vertical(cont, output);
|
||||
print_troff_ms_vertical(cont, fout);
|
||||
else
|
||||
print_troff_ms_text(cont, output);
|
||||
print_troff_ms_text(cont, fout);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, _("invalid output format (internal error): %d"),
|
||||
fprintf(stderr, _("invalid fout format (internal error): %d"),
|
||||
cont->opt->format);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (is_pager)
|
||||
ClosePager(output);
|
||||
ClosePager(fout);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user