diff options
| -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;  | 
