On Wed, Nov 08, 2017 at 04:00:35PM +0100, Michal Privoznik wrote:
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(a)redhat.com>
>> ---
>> 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?
Sure, I agree, my question was if this is using it just for filtering strings,
looks like yes :D
Michal
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list