The way we currently call completer callbacks is that if we've found --option that user wants to complete value for and it has callback set then the callback is called. And just before that, if no --option to have the value completed is found or is found and is of boolean type then a list of --option is generated (for given command). But these two conditions can never be true at the same time because boolean type of --options do not accept values. Therefore the calling of completer callback can be promoted onto the same level as the --option list generation. This means that merging of two lists can be dropped to and completer callback can store its retval directly into @list (but as shown earlier one of the string lists to merge is always empty). Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- tools/vsh.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index e0dbda04c8..0d3c4fd7c7 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -2750,34 +2750,28 @@ vshReadlineParse(const char *text, int state) if (!cmd) { list = vshReadlineCommandGenerator(text); - } else { - if (!opt || opt->type == VSH_OT_BOOL) - list = vshReadlineOptionsGenerator(text, cmd, partial); + } else if (!opt || opt->type == VSH_OT_BOOL) { + list = vshReadlineOptionsGenerator(text, cmd, partial); + } else if (opt && opt->completer) { + list = opt->completer(autoCompleteOpaque, + partial, + opt->completer_flags); + } - if (opt && opt->completer) { - g_auto(GStrv) completer_list = opt->completer(autoCompleteOpaque, - partial, - opt->completer_flags); + /* Escape completions, if needed (i.e. argument + * we are completing wasn't started with a quote + * character). This also enables filtering done + * below to work properly. */ + if (list && + !rl_completion_quote_character) { + size_t i; - /* Escape completions, if needed (i.e. argument - * we are completing wasn't started with a quote - * character). This also enables filtering done - * below to work properly. */ - if (completer_list && - !rl_completion_quote_character) { - size_t i; + for (i = 0; list[i]; i++) { + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; - for (i = 0; completer_list[i]; i++) { - g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; - - virBufferEscape(&buf, '\\', " ", "%s", completer_list[i]); - VIR_FREE(completer_list[i]); - completer_list[i] = virBufferContentAndReset(&buf); - } - } - - if (virStringListMerge(&list, &completer_list) < 0) - goto cleanup; + virBufferEscape(&buf, '\\', " ", "%s", list[i]); + VIR_FREE(list[i]); + list[i] = virBufferContentAndReset(&buf); } } -- 2.26.2