From 199b87deb39c393562d96dec56c565e25ae76edc Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" Date: Thu, 2 May 2024 22:28:15 +0500 Subject: [PATCH v1] Add URLs to \h in psql when there is no match --- src/bin/psql/help.c | 44 ++++++++++++++++++++++++++++++++++++++++- src/bin/psql/settings.h | 3 +++ src/bin/psql/startup.c | 11 +++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 4e79a819d8..703597289e 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -422,6 +422,8 @@ helpVariables(unsigned short int pager) " specifies the prompt used when a statement continues from a previous line\n"); HELP0(" PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n"); + HELP0(" HELP_URLS\n" + " specifies |-separated array of URLs with \%s\n"); HELP0(" QUIET\n" " run quietly (same as -q option)\n"); HELP0(" ROW_COUNT\n" @@ -558,6 +560,30 @@ helpVariables(unsigned short int pager) } +static char *url_encode(const char *input) { + /* Allocate enough space for the encoded string */ + char *output = calloc(strlen(input) * 3 + 1, sizeof(char)); + int output_pos = 0; + + for (int i = 0; input[i]; i++) { + unsigned char c = input[i]; + if (c == ' ') { + output[output_pos++] = '%'; + output[output_pos++] = '2'; + output[output_pos++] = '0'; + } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') { + output[output_pos++] = c; + } else { + output[output_pos++] = '%'; + output[output_pos++] = "0123456789ABCDEF"[c >> 4]; + output[output_pos++] = "0123456789ABCDEF"[c & 0xF]; + } + } + + return output; +} + + /* * helpSQL -- help with SQL commands * @@ -713,10 +739,26 @@ helpSQL(const char *topic, unsigned short int pager) /* If we never found anything, report that */ if (!output) { + char* urls; + char* url; + char* encoded_topic; output = PageOutput(2, pager ? &(pset.popt.topt) : NULL); fprintf(output, _("No help available for \"%s\".\n" - "Try \\h with no arguments to see available help.\n"), + "Try \\h with no arguments to see available help or search online:\n"), topic); + /* TODO: URL encode topic*/ + encoded_topic = url_encode(topic); + urls = pstrdup(pset.help_urls); + url = strtok(urls,"|"); + while (url != NULL) + { + fprintf(output, "\nURL: "); + fprintf(output, url, encoded_topic); + fprintf(output, "\n"); + url = strtok(NULL, "|"); + } + fprintf(output, "\n"); + free(encoded_topic); } ClosePager(output); diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index 505f99d8e4..0be1300738 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -27,6 +27,8 @@ #define DEFAULT_PROMPT2 "%/%R%x%# " #define DEFAULT_PROMPT3 ">> " +#define DEFAULT_HELP_URLS "https://www.postgresql.org/search/?q=%s" + /* * Note: these enums should generally be chosen so that zero corresponds * to the default behavior. @@ -151,6 +153,7 @@ typedef struct _psqlSettings const char *prompt1; const char *prompt2; const char *prompt3; + const char *help_urls; PGVerbosity verbosity; /* current error verbosity level */ bool show_all_results; PGContextVisibility show_context; /* current context display level */ diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 036caaec2f..824297fd57 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -203,6 +203,7 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); + SetVariable(pset.vars, "HELP_URLS", DEFAULT_HELP_URLS); SetVariableBool(pset.vars, "SHOW_ALL_RESULTS"); parse_psql_options(argc, argv, &options); @@ -1115,6 +1116,13 @@ prompt3_hook(const char *newval) return true; } +static bool +help_urls_hook(const char *newval) +{ + pset.help_urls = newval ? newval : ""; + return true; +} + static char * verbosity_substitute_hook(char *newval) { @@ -1250,6 +1258,9 @@ EstablishVariableSpace(void) SetVariableHooks(pset.vars, "PROMPT3", NULL, prompt3_hook); + SetVariableHooks(pset.vars, "HELP_URLS", + NULL, + help_urls_hook); SetVariableHooks(pset.vars, "VERBOSITY", verbosity_substitute_hook, verbosity_hook); -- 2.37.1 (Apple Git-137.1)