Re: Support tab completion for upper character inputs in psql - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Support tab completion for upper character inputs in psql
Date
Msg-id 838381.1643665141@sss.pgh.pa.us
Whole thread Raw
In response to Re: Support tab completion for upper character inputs in psql  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Support tab completion for upper character inputs in psql  (Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>)
List pgsql-hackers
I wrote:
> =?utf-8?Q?Dagfinn_Ilmari_Manns=C3=A5ker?= <ilmari@ilmari.org> writes:
>> First, as noted in the test, it doesn't preserve the case of the input
>> for keywords appended to the query result.  This is easily fixed by
>> using `pg_strdup_keyword_case()`, per the first attached patch.

> I thought about that, and intentionally didn't do it, because it
> would also affect the menus produced by tab completion.
> ...
> We could do something hacky like matching case only when there's
> no longer any matching object names, but that might be too magic.

I experimented with that, and it actually doesn't seem as weird
as I feared.  See if you like this ...

            regards, tom lane

diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl
index c4f6552ac9..7a265e0676 100644
--- a/src/bin/psql/t/010_tab_completion.pl
+++ b/src/bin/psql/t/010_tab_completion.pl
@@ -40,7 +40,7 @@ $node->start;

 # set up a few database objects
 $node->safe_psql('postgres',
-        "CREATE TABLE tab1 (f1 int primary key, f2 text);\n"
+        "CREATE TABLE tab1 (c1 int primary key, c2 text);\n"
       . "CREATE TABLE mytab123 (f1 int, f2 text);\n"
       . "CREATE TABLE mytab246 (f1 int, f2 text);\n"
       . "CREATE TABLE \"mixedName\" (f1 int, f2 text);\n"
@@ -317,14 +317,30 @@ check_completion(

 clear_line();

-# check completion of a keyword offered in addition to object names
-# (that code path currently doesn't preserve case of what's typed)
-check_completion(
-    "comment on constraint foo on dom\t",
-    qr|DOMAIN|,
-    "offer keyword in addition to query result");
-
-clear_query();
+# check completion of a keyword offered in addition to object names;
+# such a keyword should obey COMP_KEYWORD_CASE once only keyword
+# completions are possible
+foreach (
+    [ 'lower',          'CO', 'column' ],
+    [ 'upper',          'co', 'COLUMN' ],
+    [ 'preserve-lower', 'co', 'column' ],
+    [ 'preserve-upper', 'CO', 'COLUMN' ],)
+{
+    my ($case, $in, $out) = @$_;
+
+    check_completion(
+        "\\set COMP_KEYWORD_CASE $case\n",
+        qr/postgres=#/,
+        "set completion case to '$case'");
+    check_completion("alter table tab1 rename c\t\t",
+        qr|COLUMN|,
+        "offer keyword COLUMN for input c<TAB>, COMP_KEYWORD_CASE = $case");
+    clear_query();
+    check_completion("alter table tab1 rename $in\t\t\t",
+        qr|$out|,
+        "offer keyword $out for input $in<TAB>, COMP_KEYWORD_CASE = $case");
+    clear_query();
+}

 # send psql an explicit \q to shut it down, else pty won't close properly
 $timer->start(5);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b2ec50b4f2..bdc9760fba 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -4742,7 +4742,8 @@ _complete_from_query(const char *simple_query,
 {
     static int    list_index,
                 num_schema_only,
-                num_other;
+                num_other,
+                num_keywords;
     static PGresult *result = NULL;
     static bool non_empty_object;
     static bool schemaquoted;
@@ -4766,6 +4767,7 @@ _complete_from_query(const char *simple_query,
         list_index = 0;
         num_schema_only = 0;
         num_other = 0;
+        num_keywords = 0;
         PQclear(result);
         result = NULL;

@@ -4986,7 +4988,10 @@ _complete_from_query(const char *simple_query,

             /* In verbatim mode, we return all the items as-is */
             if (verbatim)
+            {
+                num_other++;
                 return pg_strdup(item);
+            }

             /*
              * In normal mode, a name requiring quoting will be returned only
@@ -5031,8 +5036,12 @@ _complete_from_query(const char *simple_query,
                 list_index++;
                 if (pg_strncasecmp(text, item, strlen(text)) == 0)
                 {
-                    num_other++;
-                    return pg_strdup(item);
+                    num_keywords++;
+                    /* Match keyword case if we are returning only keywords */
+                    if (num_schema_only == 0 && num_other == 0)
+                        return pg_strdup_keyword_case(item, text);
+                    else
+                        return pg_strdup(item);
                 }
             }
         }
@@ -5049,8 +5058,12 @@ _complete_from_query(const char *simple_query,
                 list_index++;
                 if (pg_strncasecmp(text, item, strlen(text)) == 0)
                 {
-                    num_other++;
-                    return pg_strdup(item);
+                    num_keywords++;
+                    /* Match keyword case if we are returning only keywords */
+                    if (num_schema_only == 0 && num_other == 0)
+                        return pg_strdup_keyword_case(item, text);
+                    else
+                        return pg_strdup(item);
                 }
             }
         }
@@ -5062,7 +5075,7 @@ _complete_from_query(const char *simple_query,
      * completion subject text, which is not what we want.
      */
 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
-    if (num_schema_only > 0 && num_other == 0)
+    if (num_schema_only > 0 && num_other == 0 && num_keywords == 0)
         rl_completion_append_character = '\0';
 #endif


pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: Support for NSS as a libpq TLS backend
Next
From: Greg Stark
Date:
Subject: Re: pg_walinspect - a new extension to get raw WAL data and WAL stats