mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
vsh: Introduce complete command
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@redhat.com>
This commit is contained in:
parent
cc005fe5a8
commit
a0e1ada63c
@ -833,6 +833,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,
|
||||
|
@ -1351,6 +1351,7 @@ static const vshCmdDef vshAdmCmds[] = {
|
||||
VSH_CMD_PWD,
|
||||
VSH_CMD_QUIT,
|
||||
VSH_CMD_SELF_TEST,
|
||||
VSH_CMD_COMPLETE,
|
||||
{.name = "uri",
|
||||
.handler = cmdURI,
|
||||
.opts = NULL,
|
||||
|
80
tools/vsh.c
80
tools/vsh.c
@ -3475,3 +3475,83 @@ 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 = "";
|
||||
const vshCmdOpt *opt = NULL;
|
||||
char **matches = NULL, **iter;
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
|
||||
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)))
|
||||
goto cleanup;
|
||||
|
||||
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
|
||||
if (virBufferUse(&buf) != 0)
|
||||
virBufferAddChar(&buf, ' ');
|
||||
virBufferAddStr(&buf, opt->data);
|
||||
arg = opt->data;
|
||||
}
|
||||
|
||||
if (virBufferCheckError(&buf) < 0)
|
||||
goto cleanup;
|
||||
|
||||
vshReadlineInit(ctl);
|
||||
|
||||
if (!(rl_line_buffer = virBufferContentAndReset(&buf)) &&
|
||||
VIR_STRDUP(rl_line_buffer, "") < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* rl_point is current cursor position in rl_line_buffer.
|
||||
* In our case it's at the end of the whole line. */
|
||||
rl_point = strlen(rl_line_buffer);
|
||||
|
||||
if (!(matches = vshReadlineCompletion(arg, 0, 0)))
|
||||
goto cleanup;
|
||||
|
||||
for (iter = matches; *iter; iter++)
|
||||
printf("%s\n", *iter);
|
||||
|
||||
ret = true;
|
||||
cleanup:
|
||||
virBufferFreeAndReset(&buf);
|
||||
virStringListFree(matches);
|
||||
#endif /* WITH_READLINE */
|
||||
return ret;
|
||||
}
|
||||
|
14
tools/vsh.h
14
tools/vsh.h
@ -382,6 +382,8 @@ extern const vshCmdInfo info_echo[];
|
||||
extern const vshCmdInfo info_pwd[];
|
||||
extern const vshCmdInfo info_quit[];
|
||||
extern const vshCmdInfo info_selftest[];
|
||||
extern const vshCmdOptDef opts_complete[];
|
||||
extern const vshCmdInfo info_complete[];
|
||||
|
||||
bool cmdHelp(vshControl *ctl, const vshCmd *cmd);
|
||||
bool cmdCd(vshControl *ctl, const vshCmd *cmd);
|
||||
@ -389,6 +391,7 @@ bool cmdEcho(vshControl *ctl, const vshCmd *cmd);
|
||||
bool cmdPwd(vshControl *ctl, const vshCmd *cmd);
|
||||
bool cmdQuit(vshControl *ctl, const vshCmd *cmd);
|
||||
bool cmdSelfTest(vshControl *ctl, const vshCmd *cmd);
|
||||
bool cmdComplete(vshControl *ctl, const vshCmd *cmd);
|
||||
|
||||
# define VSH_CMD_CD \
|
||||
{ \
|
||||
@ -454,6 +457,17 @@ bool cmdSelfTest(vshControl *ctl, const vshCmd *cmd);
|
||||
.alias = "self-test" \
|
||||
}
|
||||
|
||||
# define VSH_CMD_COMPLETE \
|
||||
{ \
|
||||
.name = "complete", \
|
||||
.handler = cmdComplete, \
|
||||
.opts = opts_complete, \
|
||||
.info = info_complete, \
|
||||
.flags = VSH_CMD_FLAG_NOCONNECT | VSH_CMD_FLAG_ALIAS, \
|
||||
.alias = "complete" \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* readline */
|
||||
char * vshReadline(vshControl *ctl, const char *prompt);
|
||||
|
Loading…
Reference in New Issue
Block a user