From nobody Sun Feb 8 20:53:38 2026 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1713532607167281.75506478549335; Fri, 19 Apr 2024 06:16:47 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 216B21D5A; Fri, 19 Apr 2024 09:16:46 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id F227F1DE5; Fri, 19 Apr 2024 09:05:58 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D56661DAE; Fri, 19 Apr 2024 09:05:46 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 4FBF61C6F for ; Fri, 19 Apr 2024 09:05:41 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-327-AYmvbVQNP-mrc0LlKD162w-1; Fri, 19 Apr 2024 09:05:39 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 55C26800CA2 for ; Fri, 19 Apr 2024 13:05:39 +0000 (UTC) Received: from speedmetal.lan (unknown [10.45.242.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id C18F22166B34 for ; Fri, 19 Apr 2024 13:05:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: AYmvbVQNP-mrc0LlKD162w-1 From: Peter Krempa To: devel@lists.libvirt.org Subject: [PATCH 06/13] vsh: Rework logic for picking which argument is to be completed Date: Fri, 19 Apr 2024 15:05:24 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: EC5RW3MS2WCVET2Z7H2NS6E2CFV52QKB X-Message-ID-Hash: EC5RW3MS2WCVET2Z7H2NS6E2CFV52QKB X-MailFrom: pkrempa@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1713532608360100001 Currently the code decides which option to complete by looking into the input string and trying to infer it based on whether we are at the end position as we truncate the string to complete to the current cursor position. That basically means that only the last-parsed option will be up for completion. Replace the logic by remembering which is the last option rather than using two different position checks and base the completion decision on that and the actual value of the last argument (see comment). Signed-off-by: Peter Krempa --- tools/vsh.c | 63 +++++++++++++++++++++++++++-------------------------- tools/vsh.h | 1 + 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index 71c0778660..8af6aeaa48 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1390,6 +1390,7 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser, vshCmd **partial) char *tkdata =3D NULL; vshCmd *clast =3D NULL; vshCmdOpt *first =3D NULL; + vshCmdOpt *last =3D NULL; const vshCmdDef *cmd =3D NULL; if (!partial) { @@ -1397,7 +1398,6 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser, vshCmd **partial) } while (1) { - vshCmdOpt *last =3D NULL; vshCommandToken tk; bool data_only =3D false; uint64_t opts_need_arg =3D 0; @@ -1406,6 +1406,7 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser, vshCmd **partial) cmd =3D NULL; first =3D NULL; + last =3D NULL; if (partial) { g_clear_pointer(partial, vshCommandFree); @@ -1589,6 +1590,7 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser, vshCmd **partial) } c->opts =3D g_steal_pointer(&first); + c->lastopt =3D last; c->def =3D cmd; c->next =3D NULL; @@ -1622,6 +1624,7 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser, vshCmd **partial) tmp =3D g_new0(vshCmd, 1); tmp->opts =3D first; + tmp->lastopt =3D last; tmp->def =3D cmd; *partial =3D tmp; @@ -2735,27 +2738,6 @@ vshReadlineOptionsGenerator(const vshCmdDef *cmd, } -static const vshCmdOptDef * -vshReadlineCommandFindOpt(const vshCmd *partial) -{ - const vshCmd *tmp =3D partial; - - while (tmp) { - const vshCmdOpt *opt =3D tmp->opts; - - while (opt) { - if (opt->completeThis) - return opt->def; - - opt =3D opt->next; - } - tmp =3D tmp->next; - } - - return NULL; -} - - static int vshCompleterFilter(char ***list, const char *text) @@ -2802,7 +2784,6 @@ vshReadlineParse(const char *text, int state) if (!state) { g_autoptr(vshCmd) partial =3D NULL; const vshCmdDef *cmd =3D NULL; - const vshCmdOptDef *opt =3D NULL; g_autofree char *line =3D g_strdup(rl_line_buffer); g_clear_pointer(&list, g_strfreev); @@ -2828,16 +2809,36 @@ vshReadlineParse(const char *text, int state) cmd =3D NULL; } - opt =3D vshReadlineCommandFindOpt(partial); - if (!cmd) { list =3D vshReadlineCommandGenerator(); - } else if (!opt || opt->type =3D=3D VSH_OT_BOOL) { - list =3D vshReadlineOptionsGenerator(cmd, partial); - } else if (opt && opt->completer) { - list =3D opt->completer(autoCompleteOpaque, - partial, - opt->completer_flags); + } else { + bool complete_argument =3D false; + + /* attempt completion only when: + - there is an argument + - it has the 'data' field filled + - it has a completer (rules out booleans) + */ + if (partial->lastopt && partial->lastopt->data && partial->las= topt->def->completer) { + /* Furthermore we want to do the completion only at the po= int of + * user's cursor. This is the case if: + * - value in 'data' is equal to 'text' (last component of= the completed command) + * - value in 'data' is a space when 'text' is empty (quir= k) + */ + if (STREQ_NULLABLE(partial->lastopt->data, text)) + complete_argument =3D true; + + if (STREQ_NULLABLE(partial->lastopt->data, " ") && *text = =3D=3D '\0') + complete_argument =3D true; + } + + if (complete_argument) { + list =3D partial->lastopt->def->completer(autoCompleteOpaq= ue, + partial, + partial->lastopt->= def->completer_flags); + } else { + list =3D vshReadlineOptionsGenerator(cmd, partial); + } } /* Escape completions, if needed (i.e. argument diff --git a/tools/vsh.h b/tools/vsh.h index a51140eeee..d2426d1e30 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -178,6 +178,7 @@ struct _vshCmdDef { struct _vshCmd { const vshCmdDef *def; /* command definition */ vshCmdOpt *opts; /* list of command arguments */ + vshCmdOpt *lastopt; /* last option of the commandline */ vshCmd *next; /* next command */ bool skipChecks; /* skip validity checks when retrieving op= ts */ }; --=20 2.44.0 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org