提交 43ee2282 编写于 作者: B Bruce Momjian

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.
上级 e6dbcb72
<!--
$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];
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)
{
/*
* 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;
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
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)
{
/*
* 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);
}
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册