From 34797796edb653d969930bbfe98c25aaacc198c0 Mon Sep 17 00:00:00 2001 From: Tim Kourt Date: Thu, 20 Apr 2017 16:23:08 -0700 Subject: [PATCH] client: Introduce command completion --- client/command.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ client/command.h | 2 ++ client/display.c | 2 ++ 3 files changed, 87 insertions(+) diff --git a/client/command.c b/client/command.c index 745bc8f5..53320342 100644 --- a/client/command.c +++ b/client/command.c @@ -26,6 +26,7 @@ #include #include +#include #include "command.h" #include "display.h" @@ -52,6 +53,88 @@ static const struct command command_list[] = { { } }; +static char *cmd_generator(const char *text, int state) +{ + static const struct l_queue_entry *entry; + static size_t index; + static size_t len; + const char *cmd; + + if (!state) { + len = strlen(text); + index = 0; + entry = l_queue_get_entries(command_families); + } + + while (entry) { + const struct command_family *family = entry->data; + + entry = entry->next; + + if (strncmp(family->name, text, len)) + continue; + + return l_strdup(family->name); + } + + while ((cmd = command_list[index].cmd)) { + index++; + + if (strncmp(cmd, text, len)) + continue; + + return l_strdup(cmd); + } + + return NULL; +} + +static char **cmd_completion_match_family_cmd(const char *family, + char *args, const char *text, + bool ends_with_space) +{ + return NULL; +} + +char **command_completion(const char *text, int start, int end) +{ + char **matches = NULL; + const char *family; + char *args; + char *prompt = NULL; + bool ends_with_space = false; + + if (!start) { + matches = rl_completion_matches(text, cmd_generator); + + goto done; + } + + prompt = rl_copy_text(0, rl_end); + + family = strtok_r(prompt, " ", &args); + if (!family) + goto done; + + if (args) { + int len = strlen(args); + + if (len > 0 && args[len - 1] == ' ') + ends_with_space = true; + } + + matches = cmd_completion_match_family_cmd(family, args, text, + ends_with_space); + +done: + l_free(prompt); + + if (!matches) + rl_attempted_completion_over = 1; + + return matches; +} + static void execute_cmd(const char *family, const char *entity, const struct command *cmd, char *args) { diff --git a/client/command.h b/client/command.h index 33ad1cdd..c3b5b587 100644 --- a/client/command.h +++ b/client/command.h @@ -37,6 +37,8 @@ struct command_family { const struct command *command_list; }; +char **command_completion(const char *text, int start, int end); + void command_process_prompt(char *prompt); void command_family_register(const struct command_family *family); diff --git a/client/display.c b/client/display.c index 42024222..79655385 100644 --- a/client/display.c +++ b/client/display.c @@ -264,6 +264,8 @@ void display_init(void) setlinebuf(stdout); + rl_attempted_completion_function = command_completion; + rl_erase_empty_line = 1; rl_callback_handler_install("Waiting for IWD to appear...", readline_callback);