From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24604 invoked by alias); 30 Jul 2015 16:27:03 -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: 35957 Received: (qmail 22362 invoked from network); 30 Jul 2015 16:27:02 -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: Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 7.3 \(1878.6\)) Subject: Re: _make-expandVars() broken? (was Re: Makefile completion with wildcard targets) From: "Jun T." In-Reply-To: <22F30644-D300-4DA7-9E18-CDA30F0AA8CA@kba.biglobe.ne.jp> Date: Fri, 31 Jul 2015 01:26:57 +0900 Content-Transfer-Encoding: 7bit Message-Id: <07E94665-98A0-4AC1-A835-3FBE1D130A25@kba.biglobe.ne.jp> References: <22F30644-D300-4DA7-9E18-CDA30F0AA8CA@kba.biglobe.ne.jp> To: zsh-workers@zsh.org X-Mailer: Apple Mail (2.1878.6) X-Biglobe-Spnum: 50835 Here is a slightly updated _make. (1)(2)(3) were already in the previous patch. (4)(5) are new. (1) fix the broken make-expandVars() (2) allow * ? and $ as the first character of the target. (3) add an option -Q to compadd for targets. (4) If 'VAR=VAL' is on the current command line, % make VAR=VAL then use it in make-expandVars(). Also do not offer VAR for completion if VAR=VAL is already on the command line (compadd -F). (5) If the variable is not defined in Makefile nor on the command line, then look it up in the environment. The option --environment-overrides is respected. It doesn't support $(SRCS:.c=.o) etc., but if a user need these then he/she can set call-command style to true to use the output from 'make -nsp'. Any comment? # The reason that make-expandVars() has been broken for a long time # may be that most of the users are setting call-command style? diff --git a/Completion/Unix/Command/_make b/Completion/Unix/Command/_make index c14a34c..48befa7 100644 --- a/Completion/Unix/Command/_make +++ b/Completion/Unix/Command/_make @@ -4,58 +4,68 @@ # are used in those targets and their dependencies. _make-expandVars() { - local open close var val front ret tmp=$1 + local open close var val front='' rest=$1 - front=${tmp%%\$*} - case $tmp in - (\(*) # Variable of the form $(foobar) - open='(' - close=')' - ;; - - ({*) # ${foobar} - open='{' - close='}' - ;; - - ([[:alpha:]]*) # $foobar. This is exactly $(f)oobar. - open='' - close='' - var=${(s::)var[1]} - ;; - - (\$*) # Escaped $. - print -- "${front}\$$(_make-expandVars ${tmp#\$})" - return - ;; + while [[ $rest == (#b)[^$]#($)* ]]; do + front=$front${rest[1,$mbegin[1]-1]} + rest=${rest[$mbegin[1],-1]} - (*) # Nothing left to substitute. - print -- $tmp - return - ;; - esac - - if [[ -n $open ]] - then - var=${tmp#$open} - var=${var%%$close*} - fi + case $rest[2] in + ($) # '$$'. may not appear in target and variable's value + front=$front\$\$ + rest=${rest[3,-1]} + continue + ;; + (\() # Variable of the form $(foobar) + open='(' + close=')' + ;; + ({) # ${foobar} + open='{' + close='}' + ;; + ([[:alpha:]]) # $foobar. This is exactly $(f)oobar. + open='' + close='' + var=$rest[2] + ;; + (*) # bad parameter name + print -- $front$rest + return 1 + ;; + esac - case $var in - ([[:alnum:]_]#) - val=${VARIABLES[$var]} - ret=${ret//\$$open$var$close/$val} - ;; + if [[ -n $open ]]; then + if [[ $rest == \$$open(#b)([[:alnum:]_]##)(#B)$close* ]]; then + var=$match + else # unmatched () or {}, or bad parameter name + print -- $front$rest + return 1 + fi + fi - (*) - # Improper variable name. No replacement. - # I'm not sure if this is desired behavior. - front+="\$$open$var$close" - ret=${ret/\$$open$var$close/} - ;; - esac + val='' + if [[ -n ${VAR_ARGS[(i)$var]} ]]; then + val=${VAR_ARGS[$var]} + else + if [[ -n $opt_args[(I)(-e|--environment-overrides)] ]]; then + if [[ $parameters[$var] == scalar-export* ]]; then + val=${(P)var} + elif [[ -n ${VARIABLES[(i)$var]} ]]; then + val=${VARIABLES[$var]} + fi + else + if [[ -n ${VARIABLES[(i)$var]} ]]; then + val=${VARIABLES[$var]} + elif [[ $parameters[$var] == scalar-export* ]]; then + val=${(P)var} + fi + fi + fi + rest=${rest//\$$open$var$close/$val} + done - print -- "${front}$(_make-expandVars ${ret})" + print -- ${front}${rest} } _make-parseMakefile () { @@ -84,16 +94,9 @@ _make-parseMakefile () { # TARGET: dependencies # TARGET1 TARGET2 TARGET3: dependencies - ([[:alnum:]][^$TAB:=]#:[^=]*) - input=$(_make-expandVars $input) - target=${input%%:*} - dep=${input#*:} - dep=${(z)dep} - dep="$dep" - for tmp in ${(z)target} - do - TARGETS[$tmp]=$dep - done + ([[*?[:alnum:]$][^$TAB:=%]#:[^=]*) + target=$(_make-expandVars ${input%%:*}) + TARGETS+=( ${(z)target} ) ;; # Include another makefile @@ -150,9 +153,18 @@ _make() { local prev="$words[CURRENT-1]" file expl tmp is_gnu dir incl match local context state state_descr line local -a option_specs - local -A TARGETS VARIABLES opt_args + local -A VARIABLES VAR_ARGS opt_args + local -aU TARGETS keys local ret=1 + # VAR=VAL on the current command line + for tmp in $words; do + if [[ $tmp == (#b)([[:alnum:]_]##)=(*) ]]; then + VAR_ARGS[${tmp[$mbegin[1],$mend[1]]}]=${(e)tmp[$mbegin[2],$mend[2]]} + fi + done + keys=( ${(k)VAR_ARGS} ) # to be used in 'compadd -F keys' + _pick_variant -r is_gnu gnu=GNU unix -v -f if [[ $is_gnu == gnu ]] @@ -275,9 +287,9 @@ _make() { while _tags do _requested targets expl 'make targets' \ - compadd -- ${(k)TARGETS} && ret=0 + compadd -Q -- $TARGETS && ret=0 _requested variables expl 'make variables' \ - compadd -S '=' -- ${(k)VARIABLES} && ret=0 + compadd -S '=' -F keys -- ${(k)VARIABLES} && ret=0 done fi esac