mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-02 13:47:13 +03:00
vshReadlineParse: Use string list
It's better to fetch list of either commands or options just once and then iterate over it. Moreover, it makes future completers way simpler as they will return string lists too. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
61fb1df74d
commit
69ebc64518
121
tools/vsh.c
121
tools/vsh.c
@ -2605,25 +2605,25 @@ vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
|
|||||||
* -----------------
|
* -----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Generator function for command completion. STATE lets us
|
* vshReadlineCommandGenerator:
|
||||||
* know whether to start from scratch; without any state
|
* @text: optional command prefix
|
||||||
* (i.e. STATE == 0), then we start at the top of the list.
|
*
|
||||||
|
* Generator function for command completion.
|
||||||
|
*
|
||||||
|
* Returns a string list of commands with @text prefix,
|
||||||
|
* NULL if there's no such command.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char **
|
||||||
vshReadlineCommandGenerator(const char *text, int state)
|
vshReadlineCommandGenerator(const char *text)
|
||||||
{
|
{
|
||||||
static unsigned int grp_list_index, cmd_list_index;
|
size_t grp_list_index = 0, cmd_list_index = 0;
|
||||||
static size_t len;
|
size_t len = strlen(text);
|
||||||
const char *name;
|
const char *name;
|
||||||
const vshCmdGrp *grp;
|
const vshCmdGrp *grp;
|
||||||
const vshCmdDef *cmds;
|
const vshCmdDef *cmds;
|
||||||
|
size_t ret_size = 0;
|
||||||
if (!state) {
|
char **ret = NULL;
|
||||||
grp_list_index = 0;
|
|
||||||
cmd_list_index = 0;
|
|
||||||
len = strlen(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
grp = cmdGroups;
|
grp = cmdGroups;
|
||||||
|
|
||||||
@ -2638,8 +2638,16 @@ vshReadlineCommandGenerator(const char *text, int state)
|
|||||||
if (cmds[cmd_list_index++].flags & VSH_CMD_FLAG_ALIAS)
|
if (cmds[cmd_list_index++].flags & VSH_CMD_FLAG_ALIAS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (STREQLEN(name, text, len))
|
if (STREQLEN(name, text, len)) {
|
||||||
return vshStrdup(NULL, name);
|
if (VIR_REALLOC_N(ret, ret_size + 2) < 0) {
|
||||||
|
virStringListFree(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret[ret_size] = vshStrdup(NULL, name);
|
||||||
|
ret_size++;
|
||||||
|
/* Terminate the string list properly. */
|
||||||
|
ret[ret_size] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cmd_list_index = 0;
|
cmd_list_index = 0;
|
||||||
@ -2647,23 +2655,17 @@ vshReadlineCommandGenerator(const char *text, int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no names matched, then return NULL. */
|
return ret;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char **
|
||||||
vshReadlineOptionsGenerator(const char *text, int state, const vshCmdDef *cmd_parsed)
|
vshReadlineOptionsGenerator(const char *text, const vshCmdDef *cmd)
|
||||||
{
|
{
|
||||||
static unsigned int list_index;
|
size_t list_index = 0;
|
||||||
static size_t len;
|
size_t len = strlen(text);
|
||||||
static const vshCmdDef *cmd;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
size_t ret_size = 0;
|
||||||
if (!state) {
|
char **ret = NULL;
|
||||||
cmd = cmd_parsed;
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2672,7 +2674,7 @@ vshReadlineOptionsGenerator(const char *text, int state, const vshCmdDef *cmd_pa
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while ((name = cmd->opts[list_index].name)) {
|
while ((name = cmd->opts[list_index].name)) {
|
||||||
char *res;
|
size_t name_len;
|
||||||
|
|
||||||
list_index++;
|
list_index++;
|
||||||
|
|
||||||
@ -2685,28 +2687,40 @@ vshReadlineOptionsGenerator(const char *text, int state, const vshCmdDef *cmd_pa
|
|||||||
} else if (STRNEQLEN(text, "--", len)) {
|
} else if (STRNEQLEN(text, "--", len)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
res = vshMalloc(NULL, strlen(name) + 3);
|
|
||||||
snprintf(res, strlen(name) + 3, "--%s", name);
|
if (VIR_REALLOC_N(ret, ret_size + 2) < 0) {
|
||||||
return res;
|
virStringListFree(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
ret[ret_size] = vshMalloc(NULL, name_len + 3);
|
||||||
|
snprintf(ret[ret_size], name_len + 3, "--%s", name);
|
||||||
|
ret_size++;
|
||||||
|
/* Terminate the string list properly. */
|
||||||
|
ret[ret_size] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no names matched, then return NULL. */
|
return ret;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
vshReadlineParse(const char *text, int state)
|
vshReadlineParse(const char *text, int state)
|
||||||
{
|
{
|
||||||
static vshCmd *partial;
|
static vshCmd *partial;
|
||||||
static const vshCmdDef *cmd;
|
static char **list;
|
||||||
char *res = NULL;
|
static size_t list_index;
|
||||||
|
const vshCmdDef *cmd = NULL;
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
char *buf = vshStrdup(NULL, rl_line_buffer);
|
char *buf = vshStrdup(NULL, rl_line_buffer);
|
||||||
|
|
||||||
vshCommandFree(partial);
|
vshCommandFree(partial);
|
||||||
partial = NULL;
|
partial = NULL;
|
||||||
cmd = NULL;
|
virStringListFree(list);
|
||||||
|
list = NULL;
|
||||||
|
list_index = 0;
|
||||||
|
|
||||||
*(buf + rl_point) = '\0';
|
*(buf + rl_point) = '\0';
|
||||||
|
|
||||||
@ -2729,26 +2743,37 @@ vshReadlineParse(const char *text, int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd) {
|
if (!list) {
|
||||||
res = vshReadlineCommandGenerator(text, state);
|
if (!cmd) {
|
||||||
} else {
|
list = vshReadlineCommandGenerator(text);
|
||||||
res = vshReadlineOptionsGenerator(text, state, cmd);
|
} else {
|
||||||
|
list = vshReadlineOptionsGenerator(text, cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res &&
|
if (list) {
|
||||||
|
ret = vshStrdup(NULL, list[list_index]);
|
||||||
|
list_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret &&
|
||||||
!rl_completion_quote_character) {
|
!rl_completion_quote_character) {
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
virBufferEscapeShell(&buf, res);
|
virBufferEscapeShell(&buf, ret);
|
||||||
VIR_FREE(res);
|
VIR_FREE(ret);
|
||||||
res = virBufferContentAndReset(&buf);
|
ret = virBufferContentAndReset(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res) {
|
if (!ret) {
|
||||||
vshCommandFree(partial);
|
vshCommandFree(partial);
|
||||||
partial = NULL;
|
partial = NULL;
|
||||||
|
virStringListFree(list);
|
||||||
|
list = NULL;
|
||||||
|
list_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **
|
static char **
|
||||||
|
Loading…
x
Reference in New Issue
Block a user