On 11/08/2017 03:23 PM, Martin Kletzander wrote: > On Tue, Nov 07, 2017 at 01:22:55PM +0100, Michal Privoznik wrote: >> This command is going to be called from bash completion script in >> the following form: >> >> virsh complete "start --domain" >> >> Its only purpose is to return list of possible strings for >> completion. Note that this is a 'hidden', unlisted command and >> therefore there's no documentation to it. >> >> Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> >> --- >> tools/virsh.c | 1 + >> tools/virt-admin.c | 1 + >> tools/vsh.c | 68 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> tools/vsh.h | 14 +++++++++++ >> 4 files changed, 84 insertions(+) >> >> diff --git a/tools/virsh.c b/tools/virsh.c >> index 7d6dc2620..f830331f6 100644 >> --- a/tools/virsh.c >> +++ b/tools/virsh.c >> @@ -846,6 +846,7 @@ static const vshCmdDef virshCmds[] = { >> VSH_CMD_PWD, >> VSH_CMD_QUIT, >> VSH_CMD_SELF_TEST, >> + VSH_CMD_COMPLETE, >> {.name = "connect", >> .handler = cmdConnect, >> .opts = opts_connect, >> diff --git a/tools/virt-admin.c b/tools/virt-admin.c >> index 5d7ef7988..c24ed95c0 100644 >> --- a/tools/virt-admin.c >> +++ b/tools/virt-admin.c >> @@ -1356,6 +1356,7 @@ static const vshCmdDef vshAdmCmds[] = { >> VSH_CMD_PWD, >> VSH_CMD_QUIT, >> VSH_CMD_SELF_TEST, >> + VSH_CMD_COMPLETE, >> {.name = "uri", >> .handler = cmdURI, >> .opts = NULL, >> diff --git a/tools/vsh.c b/tools/vsh.c >> index 121669574..136acb0ab 100644 >> --- a/tools/vsh.c >> +++ b/tools/vsh.c >> @@ -3419,3 +3419,71 @@ cmdSelfTest(vshControl *ctl ATTRIBUTE_UNUSED, >> >> return true; >> } >> + >> +/* ---------------------- >> + * Autocompletion command >> + * ---------------------- */ >> + >> +const vshCmdOptDef opts_complete[] = { >> + {.name = "string", >> + .type = VSH_OT_ARGV, >> + .flags = VSH_OFLAG_EMPTY_OK, >> + .help = N_("partial string to autocomplete") >> + }, >> + {.name = NULL} >> +}; >> + >> +const vshCmdInfo info_complete[] = { >> + {.name = "help", >> + .data = N_("internal command for autocompletion") >> + }, >> + {.name = "desc", >> + .data = N_("internal use only") >> + }, >> + {.name = NULL} >> +}; >> + >> +bool >> +cmdComplete(vshControl *ctl, const vshCmd *cmd) >> +{ >> + bool ret = false; >> +#ifdef WITH_READLINE >> + const vshClientHooks *hooks = ctl->hooks; >> + int stdin_fileno = STDIN_FILENO; >> + const char *arg = NULL; >> + char **matches = NULL, *tmp = NULL, **iter; >> + >> + if (vshCommandOptStringQuiet(ctl, cmd, "string", &arg) <= 0) >> + goto cleanup; >> + >> + /* This command is flagged VSH_CMD_FLAG_NOCONNECT because we >> + * need to prevent auth hooks reading any input. Therefore we >> + * have to close stdin and then connect ourselves. */ >> + VIR_FORCE_CLOSE(stdin_fileno); >> + >> + if (!(hooks && hooks->connHandler && hooks->connHandler(ctl, true))) >> + goto cleanup; >> + >> + autoCompleteOpaque = ctl; >> + >> + rl_basic_word_break_characters = " \t\n\\`@$><=;|&{("; >> + if (VIR_STRDUP(rl_line_buffer, arg) < 0) >> + goto cleanup; >> + >> + while ((tmp = strpbrk(arg, rl_basic_word_break_characters))) >> + arg = tmp + 1; >> + >> + if (!(matches = vshReadlineCompletion(arg, 0, 0))) >> + goto cleanup; >> + >> + for (iter = matches; *iter; iter++) >> + printf("%s\n", *iter); >> + >> + ret = true; >> + cleanup: >> + for (iter = matches; iter && *iter; iter++) >> + VIR_FREE(*iter); >> + VIR_FREE(matches); >> +#endif /* WITH_READLINE */ > > Do we really need readline for it? Did I miss something or are we > really just using it here just so we don't have to split the > vshReadlineParse() in some way? Don't get me wrong, I'm OK with that, > the split would be too complicated and who doesn't use readline, right? > It just feels weird. Yes we do need readline unfortunately. vshReadlineCompletion() calls rl_completion_matches() which filters strings returned by vshReadlineParse() so that list of strings presented to user corresponds to their input. We could reimplement the rl_* function ourselves if we really want to be readline independent. On the other hand - readline is everywhere, so why should we bother? Michal -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list