From d1ddf7e9585eea836a47847602f7b05038856a49 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 13 Apr 2016 12:34:14 +0200 Subject: [PATCH] redis-cli hints. --- deps/linenoise/linenoise.c | 8 ++++++ deps/linenoise/linenoise.h | 2 +- src/redis-cli.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/deps/linenoise/linenoise.c b/deps/linenoise/linenoise.c index 368cd05c7..a807d9b8a 100644 --- a/deps/linenoise/linenoise.c +++ b/deps/linenoise/linenoise.c @@ -815,6 +815,14 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, history_len--; free(history[history_len]); if (mlmode) linenoiseEditMoveEnd(&l); + if (hintsCallback) { + /* Force a refresh without hints to leave the previous + * line as the user typed it after a newline. */ + linenoiseHintsCallback *hc = hintsCallback; + hintsCallback = NULL; + refreshLine(&l); + hintsCallback = hc; + } return (int)l.len; case CTRL_C: /* ctrl-c */ errno = EAGAIN; diff --git a/deps/linenoise/linenoise.h b/deps/linenoise/linenoise.h index 3138c1f20..ed20232c5 100644 --- a/deps/linenoise/linenoise.h +++ b/deps/linenoise/linenoise.h @@ -50,7 +50,7 @@ typedef struct linenoiseCompletions { typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); -typedef char*(linenoiseFreeHintsCallback)(char *); +typedef void(linenoiseFreeHintsCallback)(void *); void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); void linenoiseSetHintsCallback(linenoiseHintsCallback *); void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); diff --git a/src/redis-cli.c b/src/redis-cli.c index 287b8a6d8..a61210344 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -314,6 +314,7 @@ static void cliOutputHelp(int argc, char **argv) { printf("\r\n"); } +/* Linenoise completion callback. */ static void completionCallback(const char *buf, linenoiseCompletions *lc) { size_t startpos = 0; int mask; @@ -342,6 +343,56 @@ static void completionCallback(const char *buf, linenoiseCompletions *lc) { } } +/* Linenoise hints callback. */ +static char *hintsCallback(const char *buf, int *color, int *bold) { + int i, argc, buflen = strlen(buf); + sds *argv = sdssplitargs(buf,&argc); + int endspace = buflen && isspace(buf[buflen-1]); + + /* Check if the argument list is empty and return ASAP. */ + if (argc == 0) { + sdsfreesplitres(argv,argc); + return NULL; + } + + for (i = 0; i < helpEntriesLen; i++) { + if (!(helpEntries[i].type & CLI_HELP_COMMAND)) continue; + + if (strcasecmp(argv[0],helpEntries[i].full) == 0) + { + *color = 90; + *bold = 0; + sds hint = sdsnew(helpEntries[i].org->params); + + /* Remove arguments from the returned hint to show only the + * ones the user did not yet typed. */ + int toremove = argc-1; + while(toremove > 0 && sdslen(hint)) { + if (hint[0] == '[') break; + if (hint[0] == ' ') toremove--; + sdsrange(hint,1,-1); + } + + /* Add an initial space if needed. */ + if (!endspace) { + sds newhint = sdsnewlen(" ",1); + newhint = sdscatsds(newhint,hint); + sdsfree(hint); + hint = newhint; + } + + sdsfreesplitres(argv,argc); + return hint; + } + } + sdsfreesplitres(argv,argc); + return NULL; +} + +static void freeHintsCallback(void *ptr) { + sdsfree(ptr); +} + /*------------------------------------------------------------------------------ * Networking / parsing *--------------------------------------------------------------------------- */ @@ -1100,6 +1151,8 @@ static void repl(void) { config.interactive = 1; linenoiseSetMultiLine(1); linenoiseSetCompletionCallback(completionCallback); + linenoiseSetHintsCallback(hintsCallback); + linenoiseSetFreeHintsCallback(freeHintsCallback); /* Only use history when stdin is a tty. */ if (isatty(fileno(stdin))) { -- GitLab