]> granicus.if.org Git - postgresql/commitdiff
Don't treat complete_from_const as equivalent to complete_from_list.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Jul 2019 18:04:42 +0000 (14:04 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Jul 2019 18:04:42 +0000 (14:04 -0400)
Commit 4f3b38fe2 supposed that complete_from_const() is equivalent to
the one-element-list case of complete_from_list(), but that's not
really true at all.  complete_from_const() supposes that the completion
is certain enough to justify wiping out whatever the user typed, while
complete_from_list() will only provide completions that match the
word-so-far.

In practice, given the lame parsing technology used by tab-complete.c,
it's fairly hard to believe that we're *ever* certain enough about
a completion to justify auto-correcting user input that doesn't match.

Hence, remove the inappropriate unification of the two cases.
As things now stand, complete_from_const() is used only for the
situation where we have no matches and we need to keep readline
from applying its default complete-with-file-names behavior.

This (mis?) behavior actually exists much further back, but
I'm hesitant to change it in released branches.  It's not too
late for v12, though, especially seeing that the aforesaid
commit is new in v12.

Per gripe from Ken Tanzer.

Discussion: https://postgr.es/m/CAD3a31XpXzrZA9TT3BqLSHghdTK+=cXjNCE+oL2Zn4+oWoc=qA@mail.gmail.com

src/bin/psql/tab-complete.c

index ca3a162bbfa9255cb21e5e7099af23ad7ca279b0..12355348c953f2fff6e9c15e34c57f15c6528fbc 100644 (file)
@@ -205,19 +205,22 @@ do { \
        matches = completion_matches(text, complete_from_versioned_schema_query); \
 } while (0)
 
+/*
+ * Caution: COMPLETE_WITH_CONST is not for general-purpose use; you probably
+ * want COMPLETE_WITH() with one element, instead.
+ */
+#define COMPLETE_WITH_CONST(cs, con) \
+do { \
+       completion_case_sensitive = (cs); \
+       completion_charp = (con); \
+       matches = completion_matches(text, complete_from_const); \
+} while (0)
+
 #define COMPLETE_WITH_LIST_INT(cs, list) \
 do { \
        completion_case_sensitive = (cs); \
-       if (!(list)[1]) \
-       { \
-               completion_charp = (list)[0]; \
-               matches = completion_matches(text, complete_from_const); \
-       } \
-       else \
-       { \
-               completion_charpp = (list); \
-               matches = completion_matches(text, complete_from_list); \
-       } \
+       completion_charpp = (list); \
+       matches = completion_matches(text, complete_from_list); \
 } while (0)
 
 #define COMPLETE_WITH_LIST(list) COMPLETE_WITH_LIST_INT(false, list)
@@ -3758,7 +3761,7 @@ psql_completion(const char *text, int start, int end)
         */
        if (matches == NULL)
        {
-               COMPLETE_WITH("");
+               COMPLETE_WITH_CONST(true, "");
 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
                rl_completion_append_character = '\0';
 #endif
@@ -4188,10 +4191,21 @@ complete_from_list(const char *text, int state)
 
 /*
  * This function returns one fixed string the first time even if it doesn't
- * match what's there, and nothing the second time. This should be used if
- * there is only one possibility that can appear at a certain spot, so
- * misspellings will be overwritten.  The string to be passed must be in
- * completion_charp.
+ * match what's there, and nothing the second time.  The string
+ * to be used must be in completion_charp.
+ *
+ * If the given string is "", this has the effect of preventing readline
+ * from doing any completion.  (Without this, readline tries to do filename
+ * completion which is seldom the right thing.)
+ *
+ * If the given string is not empty, readline will replace whatever the
+ * user typed with that string.  This behavior might be useful if it's
+ * completely certain that we know what must appear at a certain spot,
+ * so that it's okay to overwrite misspellings.  In practice, given the
+ * relatively lame parsing technology used in this file, the level of
+ * certainty is seldom that high, so that you probably don't want to
+ * use this.  Use complete_from_list with a one-element list instead;
+ * that won't try to auto-correct "misspellings".
  */
 static char *
 complete_from_const(const char *text, int state)