psql-cp-completion.patch
text/x-patch
Filename: psql-cp-completion.patch
Type: text/x-patch
Part: 0
Message:
psql case preserving completion
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/bin/psql/tab-complete.c | 57 | 11 |
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index a27ef69..5d042f0 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -132,6 +132,7 @@ static const char *const * completion_charpp; /* to pass a list of strings */
static const char *completion_info_charp; /* to pass a second string */
static const char *completion_info_charp2; /* to pass a third string */
static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
+static bool completion_case_sensitive; /* completion is case sensitive */
/*
* A few macros to ease typing. You can use these to complete the given
@@ -155,15 +156,24 @@ do { \
matches = completion_matches(text, complete_from_schema_query); \
} while (0)
+#define COMPLETE_WITH_LIST_CS(list) \
+do { \
+ completion_charpp = list; \
+ completion_case_sensitive = true; \
+ matches = completion_matches(text, complete_from_list); \
+} while (0)
+
#define COMPLETE_WITH_LIST(list) \
do { \
completion_charpp = list; \
+ completion_case_sensitive = false; \
matches = completion_matches(text, complete_from_list); \
} while (0)
#define COMPLETE_WITH_CONST(string) \
do { \
completion_charp = string; \
+ completion_case_sensitive = false; \
matches = completion_matches(text, complete_from_const); \
} while (0)
@@ -771,7 +781,7 @@ psql_completion(char *text, int start, int end)
/* If a backslash command was started, continue */
if (text[0] == '\\')
- COMPLETE_WITH_LIST(backslash_commands);
+ COMPLETE_WITH_LIST_CS(backslash_commands);
/* Variable interpolation */
else if (text[0] == ':' && text[1] != ':')
@@ -2864,7 +2874,7 @@ psql_completion(char *text, int start, int end)
"null", "fieldsep", "tuples_only", "title", "tableattr",
"linestyle", "pager", "recordsep", NULL};
- COMPLETE_WITH_LIST(my_list);
+ COMPLETE_WITH_LIST_CS(my_list);
}
else if (strcmp(prev2_wd, "\\pset") == 0)
{
@@ -2874,14 +2884,14 @@ psql_completion(char *text, int start, int end)
{"unaligned", "aligned", "wrapped", "html", "latex",
"troff-ms", NULL};
- COMPLETE_WITH_LIST(my_list);
+ COMPLETE_WITH_LIST_CS(my_list);
}
else if (strcmp(prev_wd, "linestyle") == 0)
{
static const char *const my_list[] =
{"ascii", "old-ascii", "unicode", NULL};
- COMPLETE_WITH_LIST(my_list);
+ COMPLETE_WITH_LIST_CS(my_list);
}
}
else if (strcmp(prev_wd, "\\set") == 0)
@@ -3234,6 +3244,31 @@ _complete_from_query(int is_schema_query, const char *text, int state)
/*
+ * Make a pg_strdup copy of s and convert it to the same case as ref.
+ */
+static char *
+pg_strdup_same_case(const char *s, const char *ref)
+{
+ char *ret, *p;
+ unsigned char first = ref[0];
+
+ if (isalpha(first))
+ {
+ ret = pg_strdup(s);
+ if (islower(first))
+ for (p = ret; *p; p++)
+ *p = pg_tolower((unsigned char) *p);
+ else
+ for (p = ret; *p; p++)
+ *p = pg_toupper((unsigned char) *p);
+ return ret;
+ }
+ else
+ return pg_strdup(s);
+}
+
+
+/*
* This function returns in order one of a fixed, NULL pointer terminated list
* of strings (if matching). This can be used if there are only a fixed number
* SQL words that can appear at certain spot.
@@ -3255,7 +3290,7 @@ complete_from_list(const char *text, int state)
{
list_index = 0;
string_length = strlen(text);
- casesensitive = true;
+ casesensitive = completion_case_sensitive;
matches = 0;
}
@@ -3270,7 +3305,14 @@ complete_from_list(const char *text, int state)
/* Second pass is case insensitive, don't bother counting matches */
if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
- return pg_strdup(item);
+ {
+ if (completion_case_sensitive)
+ return pg_strdup(item);
+ else
+ /* If case insensitive matching was requested initially, return
+ * it in the case of what was already entered. */
+ return pg_strdup_same_case(item, text);
+ }
}
/*
@@ -3300,12 +3342,16 @@ complete_from_list(const char *text, int state)
static char *
complete_from_const(const char *text, int state)
{
- (void) text; /* We don't care about what was entered
- * already. */
-
psql_assert(completion_charp);
if (state == 0)
- return pg_strdup(completion_charp);
+ {
+ if (completion_case_sensitive)
+ return pg_strdup(completion_charp);
+ else
+ /* If case insensitive matching was requested initially, return it
+ * in the case of what was already entered. */
+ return pg_strdup_same_case(completion_charp, text);
+ }
else
return NULL;
}
@@ -3351,7 +3397,7 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
}
varnames[nvars] = NULL;
- COMPLETE_WITH_LIST(varnames);
+ COMPLETE_WITH_LIST_CS(varnames);
for (i = 0; i < nvars; i++)
free((void *) varnames[i]);