diff options
Diffstat (limited to 'degesch.c')
-rw-r--r-- | degesch.c | 110 |
1 files changed, 82 insertions, 28 deletions
@@ -12358,15 +12358,12 @@ completion_locate (struct completion *self, size_t offset) self->location = i - 1; } -static bool -completion_matches (struct completion *self, int word, const char *pattern) +static char * +completion_word (struct completion *self, int word) { hard_assert (word >= 0 && word < (int) self->words_len); - char *text = xstrndup (self->line + self->words[word].start, + return xstrndup (self->line + self->words[word].start, self->words[word].end - self->words[word].start); - bool result = !fnmatch (pattern, text, 0); - free (text); - return result; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -12462,6 +12459,66 @@ complete_option (struct app_context *ctx, struct completion *data, } static void +complete_set_value (struct config_item *item, const char *word, + struct strv *output) +{ + struct str serialized = str_make (); + config_item_write (item, false, &serialized); + if (!strncmp (serialized.str, word, strlen (word))) + strv_append_owned (output, str_steal (&serialized)); + else + str_free (&serialized); +} + +static void +complete_set_value_array (struct config_item *item, const char *word, + struct strv *output) +{ + if (!item->schema || item->schema->type != CONFIG_ITEM_STRING_ARRAY) + return; + + struct strv items = strv_make (); + cstr_split (item->value.string.str, ",", false, &items); + for (size_t i = 0; i < items.len; i++) + { + struct str wrapped = str_make (), serialized = str_make (); + str_append (&wrapped, items.vector[i]); + config_item_write_string (&serialized, &wrapped); + str_free (&wrapped); + + if (!strncmp (serialized.str, word, strlen (word))) + strv_append_owned (output, str_steal (&serialized)); + else + str_free (&serialized); + } + strv_free (&items); +} + +static void +complete_set (struct app_context *ctx, struct completion *data, + const char *word, struct strv *output) +{ + if (data->location == 1) + { + complete_option (ctx, data, word, output); + return; + } + if (data->location != 3) + return; + + char *key = completion_word (data, 1); + struct config_item *item = config_item_get (ctx->config.root, key, NULL); + if (item) + { + char *op = completion_word (data, 2); + if (!strcmp (op, "-=")) complete_set_value_array (item, word, output); + if (!strcmp (op, "=")) complete_set_value (item, word, output); + free (op); + } + free (key); +} + +static void complete_topic (struct app_context *ctx, struct completion *data, const char *word, struct strv *output) { @@ -12514,33 +12571,30 @@ static char ** complete_word (struct app_context *ctx, struct completion *data, const char *word) { - // First figure out what exactly we need to complete - bool try_commands = false; - bool try_options = false; - bool try_topic = false; - bool try_nicknames = false; - - if (data->location == 0 && completion_matches (data, 0, "/*")) - try_commands = true; - else if (data->location == 1 && completion_matches (data, 0, "/set")) - try_options = true; - else if (data->location == 1 && completion_matches (data, 0, "/help")) - try_commands = try_options = true; - else if (data->location == 1 && completion_matches (data, 0, "/topic")) - try_topic = try_nicknames = true; - else - try_nicknames = true; + char *initial = completion_word (data, 0); + // Start with a placeholder for the longest common prefix struct strv words = strv_make (); - - // Add placeholder strv_append_owned (&words, NULL); - if (try_commands) complete_command (ctx, data, word, &words); - if (try_options) complete_option (ctx, data, word, &words); - if (try_topic) complete_topic (ctx, data, word, &words); - if (try_nicknames) complete_nicknames (ctx, data, word, &words); + if (data->location == 0 && *initial == '/') + complete_command (ctx, data, word, &words); + else if (data->location >= 1 && !strcmp (initial, "/set")) + complete_set (ctx, data, word, &words); + else if (data->location == 1 && !strcmp (initial, "/help")) + { + complete_command (ctx, data, word, &words); + complete_option (ctx, data, word, &words); + } + else if (data->location == 1 && !strcmp (initial, "/topic")) + { + complete_topic (ctx, data, word, &words); + complete_nicknames (ctx, data, word, &words); + } + else + complete_nicknames (ctx, data, word, &words); + cstr_set (&initial, NULL); LIST_FOR_EACH (struct hook, iter, ctx->completion_hooks) { struct completion_hook *hook = (struct completion_hook *) iter; |