]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vsh: Call vshCmdOptDef completer
authorMichal Privoznik <mprivozn@redhat.com>
Tue, 21 Nov 2017 16:45:50 +0000 (17:45 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 11 Jan 2018 17:53:04 +0000 (18:53 +0100)
Now that we have everything prepared we can call options'
completer again. At the same time, pass partially parsed input to
the completer callback - it will help the callbacks to narrow
down the list of returned options based on user's input. For
instance, if the completer is supposed to return list of
interfaces depending on user input it may return just those
interfaces defined for already specified domain. Of course,
completers might ignore this parameter.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
tools/vsh.c
tools/vsh.h

index 2d1be20bd6157763159368571ec2e82a98cfa276..9fbbfb47677feb63d00bd7a56af19f4fe591ae1f 100644 (file)
@@ -2708,6 +2708,36 @@ vshReadlineOptionsGenerator(const char *text, const vshCmdDef *cmd)
     return ret;
 }
 
+
+static const vshCmdOptDef *
+vshReadlineCommandFindOpt(const vshCmd *partial,
+                          const char *text)
+{
+    const vshCmd *tmp = partial;
+
+    while (tmp && tmp->next) {
+        if (tmp->def == tmp->next->def &&
+            !tmp->next->opts)
+            break;
+        tmp = tmp->next;
+    }
+
+    if (tmp && tmp->opts) {
+        const vshCmdOpt *opt = tmp->opts;
+
+        while (opt) {
+            if (STREQ_NULLABLE(opt->data, text) ||
+                STREQ_NULLABLE(opt->data, " "))
+                return opt->def;
+
+            opt = opt->next;
+        }
+    }
+
+    return NULL;
+}
+
+
 static char *
 vshReadlineParse(const char *text, int state)
 {
@@ -2715,6 +2745,7 @@ vshReadlineParse(const char *text, int state)
     static char **list;
     static size_t list_index;
     const vshCmdDef *cmd = NULL;
+    const vshCmdOptDef *opt = NULL;
     char *ret = NULL;
 
     if (!state) {
@@ -2732,8 +2763,10 @@ vshReadlineParse(const char *text, int state)
 
         VIR_FREE(buf);
 
-        if (partial)
+        if (partial) {
             cmd = partial->def;
+            partial->skipChecks = true;
+        }
 
         if (cmd && STREQ(cmd->name, text)) {
             /* Corner case - some commands share prefix (e.g.
@@ -2745,13 +2778,26 @@ vshReadlineParse(const char *text, int state)
              */
             cmd = NULL;
         }
+
+        opt = vshReadlineCommandFindOpt(partial, text);
     }
 
     if (!list) {
         if (!cmd) {
             list = vshReadlineCommandGenerator(text);
         } else {
-            list = vshReadlineOptionsGenerator(text, cmd);
+            if (!opt || (opt->type != VSH_OT_DATA && opt->type != VSH_OT_STRING))
+                list = vshReadlineOptionsGenerator(text, cmd);
+
+            if (opt && opt->completer) {
+                char **completer_list = opt->completer(autoCompleteOpaque,
+                                                       partial,
+                                                       opt->completer_flags);
+                if (virStringListMerge(&list, &completer_list) < 0) {
+                    virStringListFree(completer_list);
+                    goto cleanup;
+                }
+            }
         }
     }
 
@@ -2768,6 +2814,7 @@ vshReadlineParse(const char *text, int state)
         ret = virBufferContentAndReset(&buf);
     }
 
+ cleanup:
     if (!ret) {
         vshCommandFree(partial);
         partial = NULL;
index 51f8ef21358fde61ed829134518cf0666664779a..ae40fb4e8e17a9441541da53137939a174ba3376 100644 (file)
@@ -124,6 +124,7 @@ typedef struct _vshCmdOptDef vshCmdOptDef;
 typedef struct _vshControl vshControl;
 
 typedef char **(*vshCompleter)(vshControl *ctl,
+                               const vshCmd *cmd,
                                unsigned int flags);
 
 /*