From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18159 invoked by alias); 28 Sep 2015 17:49:02 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 36677 Received: (qmail 14762 invoked from network); 28 Sep 2015 17:49:01 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.0 X-Biglobe-Sender: From: "Jun T." Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Subject: [PATCH] handle options of _arguments correctly Message-Id: Date: Tue, 29 Sep 2015 01:55:22 +0900 To: zsh-workers@zsh.org Mime-Version: 1.0 (Mac OS X Mail 7.3 \(1878.6\)) X-Mailer: Apple Mail (2.1878.6) X-Biglobe-Spnum: 51640 Among the options of _arguments, -S, -A and -M are not handled by the while loop at lines 295-306 of _arguments. This causes the following problem: % compdef '_arguments -S -C : -a' foo % foo - this offers -C in addition to -a. The reason is that, in _arguments, since -S is not handled by the while loop, both -S and -C remain in "$@" and passed to comparguments -i "$autod" "$singopt[@]" "$@" (line 321) Then "comparguments -i" interprets -S as an option to _arguments, but treats -C as an optspec (i.e., as an option of foo). Moreover, $usecc is not set to "yes" and -C does not have the expeced effect. So we need to handle -S -A and -M in the while loop and move them to $singopt (so that $usecc is set to yes and -C is removed from "$@"). But even with this change, there is another problem: % bar() { echo '\t-a\n\t-s' } % compdef '_arguments --' bar % bar - this correctly offers -a and -s. But % unset _args_cache_bar # or restart another zsh % compdef '_arguments -s --' bar # or '_arguments -s : --' % bar - now -s is not offered. This is because, at line 18 of _arguments, $tmpargv is set to '-s', which is used at line 144 to remove -s from $lopts; i.e., -s is considered as an optspec, not an option to _arguments itself. A simple fix would be to move the while loop (lines 295-306) to the top of _arguments. This leads to the following patch. Are there any unexpected side effects of this? diff --git a/Completion/Base/Utility/_arguments = b/Completion/Base/Utility/_arguments index 1f35e8d..551587b 100644 --- a/Completion/Base/Utility/_arguments +++ b/Completion/Base/Utility/_arguments @@ -8,6 +8,25 @@ local oldcontext=3D"$curcontext" hasopts rawret optarg = singopt alwopt local setnormarg start rest local -a match mbegin mend =20 +subopts=3D() +singopt=3D() +while [[ "$1" =3D -([AMO]*|[CRSWnsw]) ]]; do + case "$1" in + -C) usecc=3Dyes; shift ;; + -O) subopts=3D( "${(@P)2}" ); shift 2 ;; + -O*) subopts=3D( "${(@P)${1[3,-1]}}" ); shift ;; + -R) rawret=3Dyes; shift;; + -n) setnormarg=3Dyes; NORMARG=3D-1; shift;; + -w) optarg=3Dyes; shift;; + -W) alwopt=3Darg; shift;; + -[Ss]) singopt+=3D( $1 ); shift;; + -[AM]) singopt+=3D( $1 $2 ); shift 2 ;; + -[AM]*) singopt+=3D( $1 ); shift ;; + esac +done + +[[ "$PREFIX" =3D [-+] ]] && alwopt=3Darg + long=3D$argv[(I)--] if (( long )); then local name tmp tmpargv @@ -290,23 +309,6 @@ if (( long )); then set -- "$tmpargv[@]" "${(@P)name}" fi =20 -subopts=3D() -singopt=3D() -while [[ "$1" =3D -(O*|[CRWnsw]) ]]; do - case "$1" in - -C) usecc=3Dyes; shift ;; - -O) subopts=3D( "${(@P)2}" ); shift 2 ;; - -O*) subopts=3D( "${(@P)${1[3,-1]}}" ); shift ;; - -R) rawret=3Dyes; shift;; - -n) setnormarg=3Dyes; NORMARG=3D-1; shift;; - -w) optarg=3Dyes; shift;; - -s) singopt=3D(-s); shift;; - -W) alwopt=3Darg; shift;; - esac -done - -[[ "$PREFIX" =3D [-+] ]] && alwopt=3Darg - zstyle -s ":completion:${curcontext}:options" auto-description autod =20 if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then