Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 43ee228

Browse files
committed
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.
1 parent e6dbcb7 commit 43ee228

File tree

2 files changed

+128
-57
lines changed

2 files changed

+128
-57
lines changed

doc/src/sgml/ref/psql-ref.sgml

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.204 2008/05/14 04:07:01 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.205 2008/05/16 16:59:05 momjian Exp $
33
PostgreSQL documentation
44
-->
55

@@ -1555,7 +1555,8 @@ lo_import 152801
15551555
<term><literal>columns</literal></term>
15561556
<listitem>
15571557
<para>
1558-
Controls the target width for the <literal>wrapped</> format.
1558+
Controls the target width for the <literal>wrapped</> format,
1559+
and width for determining if wide output requires the pager.
15591560
Zero (the default) causes the <literal>wrapped</> format to
15601561
affect only screen output.
15611562
</para>
@@ -1717,10 +1718,9 @@ lo_import 152801
17171718
When the pager is <literal>off</>, the pager is not used. When the pager
17181719
is <literal>on</>, the pager is used only when appropriate, i.e. the
17191720
output is to a terminal and will not fit on the screen.
1720-
(<application>psql</> does not do a perfect job of estimating
1721-
when to use the pager.) <literal>\pset pager</> turns the
1722-
pager on and off. Pager can also be set to <literal>always</>,
1723-
which causes the pager to be always used.
1721+
<literal>\pset pager</> turns the pager on and off. Pager can
1722+
also be set to <literal>always</>, which causes the pager to be
1723+
always used.
17241724
</para>
17251725
</listitem>
17261726
</varlistentry>
@@ -2734,8 +2734,9 @@ $endif
27342734

27352735
<listitem>
27362736
<para>
2737-
Used for the <literal>wrapped</> output format if
2738-
<literal>\pset columns</> is zero.
2737+
If <literal>\pset columns</> is zero, controls the
2738+
width for the <literal>wrapped</> format and width for determining
2739+
if wide output requires the pager.
27392740
</para>
27402741
</listitem>
27412742
</varlistentry>

src/bin/psql/print.c

+119-49
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.101 2008/05/13 00:14:11 alvherre Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.102 2008/05/16 16:59:05 momjian Exp $
77
*/
88
#include "postgres_fe.h"
99

@@ -45,6 +45,8 @@ static char *thousands_sep;
4545

4646
/* Local functions */
4747
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
48+
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
49+
FILE **fout, bool *is_pager);
4850

4951

5052
static void *
@@ -394,7 +396,7 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
394396
* Print pretty boxes around cells.
395397
*/
396398
static void
397-
print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
399+
print_aligned_text(const printTableContent *cont, FILE *fout)
398400
{
399401
bool opt_tuples_only = cont->opt->tuples_only;
400402
bool opt_numeric_locale = cont->opt->numericLocale;
@@ -416,6 +418,8 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
416418
unsigned char **format_buf;
417419
unsigned int width_total;
418420
unsigned int total_header_width;
421+
unsigned int extra_row_output_lines = 0;
422+
unsigned int extra_output_lines = 0;
419423

420424
const char * const *ptr;
421425

@@ -424,6 +428,7 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
424428
bool *header_done; /* Have all header lines been output? */
425429
int *bytes_output; /* Bytes output for column value */
426430
int output_columns = 0; /* Width of interactive console */
431+
bool is_pager = false;
427432

428433
if (cancel_pressed)
429434
return;
@@ -476,9 +481,14 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
476481
max_nl_lines[i] = nl_lines;
477482
if (bytes_required > max_bytes[i])
478483
max_bytes[i] = bytes_required;
484+
if (nl_lines > extra_row_output_lines)
485+
extra_row_output_lines = nl_lines;
479486

480487
width_header[i] = width;
481488
}
489+
/* Add height of tallest header column */
490+
extra_output_lines += extra_row_output_lines;
491+
extra_row_output_lines = 0;
482492

483493
/* scan all cells, find maximum width, compute cell_count */
484494
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)
487497
nl_lines,
488498
bytes_required;
489499

490-
/* Get width, ignore nl_lines */
491500
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
492501
&width, &nl_lines, &bytes_required);
493502
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)
552561
for (i = 0; i < col_count; i++)
553562
width_wrap[i] = max_width[i];
554563

555-
if (cont->opt->format == PRINT_WRAPPED)
564+
/*
565+
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
566+
*/
567+
if (cont->opt->columns > 0)
568+
output_columns = cont->opt->columns;
569+
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
556570
{
557-
/*
558-
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
559-
*/
560-
if (cont->opt->columns > 0)
561-
output_columns = cont->opt->columns;
562-
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
563-
{
564-
if (cont->opt->env_columns > 0)
565-
output_columns = cont->opt->env_columns;
571+
if (cont->opt->env_columns > 0)
572+
output_columns = cont->opt->env_columns;
566573
#ifdef TIOCGWINSZ
567-
else
568-
{
569-
struct winsize screen_size;
570-
571-
if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
572-
output_columns = screen_size.ws_col;
573-
}
574-
#endif
574+
else
575+
{
576+
struct winsize screen_size;
577+
578+
if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
579+
output_columns = screen_size.ws_col;
575580
}
581+
#endif
582+
}
576583

584+
if (cont->opt->format == PRINT_WRAPPED)
585+
{
577586
/*
578587
* Optional optimized word wrap. Shrink columns with a high max/avg
579588
* ratio. Slighly bias against wider columns. (Increases chance a
@@ -623,6 +632,49 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
623632
}
624633
}
625634

635+
/* If we wrapped beyond the display width, use the pager */
636+
if (!is_pager && output_columns > 0 &&
637+
(output_columns < total_header_width || output_columns < width_total))
638+
{
639+
fout = PageOutput(INT_MAX, cont->opt->pager); /* force pager */
640+
is_pager = true;
641+
}
642+
643+
/* Check if newlines or our wrapping now need the pager */
644+
if (!is_pager)
645+
{
646+
/* scan all cells, find maximum width, compute cell_count */
647+
for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
648+
{
649+
int width,
650+
nl_lines,
651+
bytes_required;
652+
653+
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
654+
&width, &nl_lines, &bytes_required);
655+
if (opt_numeric_locale && cont->align[i % col_count] == 'r')
656+
width += additional_numeric_locale_len(*ptr);
657+
658+
/*
659+
* A row can have both wrapping and newlines that cause
660+
* it to display across multiple lines. We check
661+
* for both cases below.
662+
*/
663+
if (width > 0 && width_wrap[i] &&
664+
(width-1) / width_wrap[i] + nl_lines > extra_row_output_lines)
665+
extra_row_output_lines = (width-1) / width_wrap[i] + nl_lines;
666+
667+
/* If last column, add tallest column height */
668+
if (i % col_count == col_count - 1)
669+
{
670+
/* Add height of tallest row */
671+
extra_output_lines += extra_row_output_lines;
672+
extra_row_output_lines = 0;
673+
}
674+
}
675+
IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager);
676+
}
677+
626678
/* time to output */
627679
if (cont->opt->start_table)
628680
{
@@ -882,6 +934,9 @@ print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
882934
for (i = 0; i < col_count; i++)
883935
free(format_buf[i]);
884936
free(format_buf);
937+
938+
if (is_pager)
939+
ClosePager(fout);
885940
}
886941

887942

@@ -2115,21 +2170,15 @@ printTableCleanup(printTableContent *content)
21152170
}
21162171

21172172
/*
2118-
* Use this to print just any table in the supported formats.
2173+
* IsPagerNeeded
2174+
*
2175+
* Setup pager if required
21192176
*/
21202177
void
2121-
printTable(const printTableContent *cont, FILE *fout, FILE *flog)
2178+
IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout,
2179+
bool *is_pager)
21222180
{
2123-
FILE *output;
2124-
bool is_pager = false;
2125-
2126-
if (cancel_pressed)
2127-
return;
2128-
2129-
if (cont->opt->format == PRINT_NOTHING)
2130-
return;
2131-
2132-
if (fout == stdout)
2181+
if (*fout == stdout)
21332182
{
21342183
int lines;
21352184

@@ -2150,58 +2199,79 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
21502199
lines++;
21512200
}
21522201

2153-
output = PageOutput(lines, cont->opt->pager);
2154-
is_pager = (output != fout);
2202+
*fout = PageOutput(lines + extra_lines, cont->opt->pager);
2203+
*is_pager = (*fout != stdout);
21552204
}
21562205
else
2157-
output = fout;
2206+
*is_pager = false;
2207+
}
2208+
2209+
/*
2210+
* Use this to print just any table in the supported formats.
2211+
*/
2212+
void
2213+
printTable(const printTableContent *cont, FILE *fout, FILE *flog)
2214+
{
2215+
bool is_pager = false;
2216+
2217+
if (cancel_pressed)
2218+
return;
2219+
2220+
if (cont->opt->format == PRINT_NOTHING)
2221+
return;
2222+
2223+
/* print_aligned_text() handles the pager itself */
2224+
if ((cont->opt->format != PRINT_ALIGNED &&
2225+
cont->opt->format != PRINT_WRAPPED) ||
2226+
cont->opt->expanded)
2227+
IsPagerNeeded(cont, 0, &fout, &is_pager);
21582228

21592229
/* print the stuff */
21602230

21612231
if (flog)
2162-
print_aligned_text(cont, is_pager, flog);
2232+
print_aligned_text(cont, flog);
21632233

21642234
switch (cont->opt->format)
21652235
{
21662236
case PRINT_UNALIGNED:
21672237
if (cont->opt->expanded)
2168-
print_unaligned_vertical(cont, output);
2238+
print_unaligned_vertical(cont, fout);
21692239
else
2170-
print_unaligned_text(cont, output);
2240+
print_unaligned_text(cont, fout);
21712241
break;
21722242
case PRINT_ALIGNED:
21732243
case PRINT_WRAPPED:
21742244
if (cont->opt->expanded)
2175-
print_aligned_vertical(cont, output);
2245+
print_aligned_vertical(cont, fout);
21762246
else
2177-
print_aligned_text(cont, is_pager, output);
2247+
print_aligned_text(cont, fout);
21782248
break;
21792249
case PRINT_HTML:
21802250
if (cont->opt->expanded)
2181-
print_html_vertical(cont, output);
2251+
print_html_vertical(cont, fout);
21822252
else
2183-
print_html_text(cont, output);
2253+
print_html_text(cont, fout);
21842254
break;
21852255
case PRINT_LATEX:
21862256
if (cont->opt->expanded)
2187-
print_latex_vertical(cont, output);
2257+
print_latex_vertical(cont, fout);
21882258
else
2189-
print_latex_text(cont, output);
2259+
print_latex_text(cont, fout);
21902260
break;
21912261
case PRINT_TROFF_MS:
21922262
if (cont->opt->expanded)
2193-
print_troff_ms_vertical(cont, output);
2263+
print_troff_ms_vertical(cont, fout);
21942264
else
2195-
print_troff_ms_text(cont, output);
2265+
print_troff_ms_text(cont, fout);
21962266
break;
21972267
default:
2198-
fprintf(stderr, _("invalid output format (internal error): %d"),
2268+
fprintf(stderr, _("invalid fout format (internal error): %d"),
21992269
cont->opt->format);
22002270
exit(EXIT_FAILURE);
22012271
}
22022272

22032273
if (is_pager)
2204-
ClosePager(output);
2274+
ClosePager(fout);
22052275
}
22062276

22072277
/*

0 commit comments

Comments
 (0)