On 01/02/2018 12:12 PM, Michal Privoznik wrote:
Similarly to the previous commit, once we've presented an
--option for a command to the user it makes no sense to offer it
again. Therefore, we can prune all already specified options. For
instance, after this patch:
virsh # migrate --verbose <TAB><TAB>
will no longer offer --verbose option.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
tools/vsh.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/tools/vsh.c b/tools/vsh.c
index 49e8033bd..f061783e0 100644
--- a/tools/vsh.c
+++ b/tools/vsh.c
@@ -2769,6 +2769,60 @@ vshCompleterFilter(char ***list,
}
+static int
+vshReadlineOptionsPrune(char ***list,
+ vshCmd *last)
+{
+ char **newList = NULL;
+ size_t newList_len = 0;
+ size_t list_len;
+ size_t i;
+
+ if (!list || !*list)
+ return -1;
+
+ if (!last->opts)
+ return 0;
+
+ list_len = virStringListLength((const char **) *list);
+
+ if (VIR_ALLOC_N(newList, list_len + 1) < 0)
+ return -1;
+
+ for (i = 0; i < list_len; i++) {
+ const char *list_opt = STRSKIP((*list)[i], "--");
+ bool exist = false;
+ vshCmdOpt *opt = last->opts;
+
+ /* Should never happen (TM) */
+ if (!list_opt)
+ return -1;
But if it does, then you'll lean newList
As reported by everyone's favorite tool!
John
+
+ while (opt) {
+ if (STREQ(opt->def->name, list_opt)) {
+ exist = true;
+ break;
+ }
+
+ opt = opt->next;
+ }
+
+ if (exist) {
+ VIR_FREE((*list)[i]);
+ continue;
+ }
+
+ VIR_STEAL_PTR(newList[newList_len], (*list)[i]);
+ newList_len++;
+ }
+
+ ignore_value(VIR_REALLOC_N_QUIET(newList, newList_len + 1));
+ VIR_FREE(*list);
+ *list = newList;
+ return 0;
+}
+
+
static char *
vshReadlineParse(const char *text, int state)
{
@@ -2817,9 +2871,13 @@ vshReadlineParse(const char *text, int state)
if (!cmd) {
list = vshReadlineCommandGenerator(text);
} else {
- if (!opt || opt->type != VSH_OT_DATA)
+ if (!opt || opt->type != VSH_OT_DATA) {
list = vshReadlineOptionsGenerator(text, cmd);
+ if (vshReadlineOptionsPrune(&list, partial) < 0)
+ goto cleanup;
+ }
+
if (opt && opt->completer) {
char **completer_list = opt->completer(autoCompleteOpaque,
partial,