Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: _make-expandVars() broken? (was Re: Makefile completion with wildcard targets)
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 <TAB>
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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author