Fix psql \h output for case of no parameters (ie, list all the known commands)
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 20 Jan 2008 21:13:55 +0000 (21:13 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 20 Jan 2008 21:13:55 +0000 (21:13 +0000)
to format properly for the actually needed column width, instead of having
a hard-wired assumption about the longest command name length.  Also make it
respond to the current screen width.  In passing, const-ify the constant
table.

src/bin/psql/create_help.pl
src/bin/psql/help.c

index fec391b27f59476f6cd2aa8994044cb0b96b1788..621d9265959c068a5dd807eda98187a6f39452d2 100644 (file)
@@ -51,20 +51,21 @@ print OUT
 #ifndef $define
 #define $define
 
-#define N_(x) (x) /* gettext noop */
+#define N_(x) (x)                              /* gettext noop */
 
 struct _helpStruct
 {
-    char          *cmd;           /* the command name */
-    char          *help;          /* the help associated with it */
-    char          *syntax;        /* the syntax associated with it */
+       const char         *cmd;                /* the command name */
+       const char         *help;               /* the help associated with it */
+       const char         *syntax;             /* the syntax associated with it */
 };
 
 
-static struct _helpStruct QL_HELP[] = {
+static const struct _helpStruct QL_HELP[] = {
 ";
 
 $count = 0;
+$maxlen = 0;
 
 foreach $file (sort readdir DIR) {
     local ($cmdname, $cmddesc, $cmdsynopsis);
@@ -113,7 +114,9 @@ foreach $file (sort readdir DIR) {
         $cmdsynopsis =~ s/\"/\\"/g;
 
        print OUT "    { \"$cmdname\",\n      N_(\"$cmddesc\"),\n      N_(\"$cmdsynopsis\") },\n\n";
-        $count++;
+
+       $count++;
+       $maxlen = ($maxlen >= length $cmdname) ? $maxlen : length $cmdname;
     }
     else {
        print STDERR "$0: parsing file '$file' failed (N='$cmdname' D='$cmddesc')\n";
@@ -125,7 +128,8 @@ print OUT "
 };
 
 
-#define QL_HELP_COUNT $count
+#define QL_HELP_COUNT  $count          /* number of help items */
+#define QL_MAX_CMD_LEN $maxlen         /* largest strlen(cmd) */
 
 
 #endif /* $define */
index 97b5f7464f6733556d3c42149729c2614b543cd0..650ae5ac0f904e26acb25ebf002f8df2a2a4b6fc 100644 (file)
 #include <win32.h>
 #endif
 
+#ifndef WIN32
+#include <sys/ioctl.h>                 /* for ioctl() */
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
 #include "pqsignal.h"
 
 #include "common.h"
@@ -147,15 +155,6 @@ usage(void)
  *
  * print out help for the backslash commands
  */
-
-#ifndef TIOCGWINSZ
-struct winsize
-{
-       int                     ws_row;
-       int                     ws_col;
-};
-#endif
-
 void
 slashUsage(unsigned short int pager)
 {
@@ -280,24 +279,46 @@ helpSQL(const char *topic, unsigned short int pager)
 
        if (!topic || strlen(topic) == 0)
        {
-               int                     i;
-               int                     items_per_column = (QL_HELP_COUNT + 2) / 3;
+               /* Print all the available command names */
+               int                     screen_width;
+               int                     ncolumns;
+               int                     nrows;
                FILE       *output;
+               int                     i;
+               int                     j;
 
-               output = PageOutput(items_per_column + 1, pager);
+#ifdef TIOCGWINSZ
+               struct winsize screen_size;
+
+               if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1)
+                       screen_width = 80;      /* ioctl failed, assume 80 */
+               else
+                       screen_width = screen_size.ws_col;
+#else
+               screen_width = 80;              /* default assumption */
+#endif
+
+               ncolumns = (screen_width - 3) / (QL_MAX_CMD_LEN + 1);
+               ncolumns = Max(ncolumns, 1);
+               nrows = (QL_HELP_COUNT + (ncolumns - 1)) / ncolumns;
+
+               output = PageOutput(nrows + 1, pager);
 
                fputs(_("Available help:\n"), output);
 
-               for (i = 0; i < items_per_column; i++)
+               for (i = 0; i < nrows; i++)
                {
-                       fprintf(output, "  %-26s%-26s",
-                                       VALUE_OR_NULL(QL_HELP[i].cmd),
-                                       VALUE_OR_NULL(QL_HELP[i + items_per_column].cmd));
-                       if (i + 2 * items_per_column < QL_HELP_COUNT)
-                               fprintf(output, "%-26s",
-                                               VALUE_OR_NULL(QL_HELP[i + 2 * items_per_column].cmd));
+                       fprintf(output, "  ");
+                       for (j = 0; j < ncolumns-1; j++)
+                               fprintf(output, "%-*s",
+                                               QL_MAX_CMD_LEN + 1,
+                                               VALUE_OR_NULL(QL_HELP[i + j * nrows].cmd));
+                       if (i + j * nrows < QL_HELP_COUNT)
+                               fprintf(output, "%s",
+                                               VALUE_OR_NULL(QL_HELP[i + j * nrows].cmd));
                        fputc('\n', output);
                }
+
                /* Only close if we used the pager */
                if (output != stdout)
                {
@@ -317,7 +338,7 @@ helpSQL(const char *topic, unsigned short int pager)
                size_t          len,
                                        wordlen;
                int                     nl_count = 0;
-               char       *ch;
+               const char *ch;
 
                /* User gets two chances: exact match, then the first word */