summaryrefslogtreecommitdiff
path: root/Completion/Unix/Command
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2009-11-24 10:01:01 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2009-11-24 10:01:01 +0000
commitb97284cde2b68af745869e030d35ef3cb7b9f079 (patch)
treea8b8dd56a2b360fdc187cd53be78259ae720fcc5 /Completion/Unix/Command
parentb7e76da2ef8e25fde84ad0c235c2bc560ea03863 (diff)
downloadzsh-b97284cde2b68af745869e030d35ef3cb7b9f079.tar.gz
zsh-b97284cde2b68af745869e030d35ef3cb7b9f079.zip
Michael Hwang <michael.a.hwang@gmail.com>: 27428:
improved _make
Diffstat (limited to 'Completion/Unix/Command')
-rw-r--r--Completion/Unix/Command/_make346
1 files changed, 197 insertions, 149 deletions
diff --git a/Completion/Unix/Command/_make b/Completion/Unix/Command/_make
index 95d7044e3..28b376bec 100644
--- a/Completion/Unix/Command/_make
+++ b/Completion/Unix/Command/_make
@@ -1,168 +1,216 @@
#compdef make gmake pmake dmake
-local prev="$words[CURRENT-1]" file expl tmp is_gnu dir incl
+# TODO: Based on targets given on the command line, show only variables that
+# are used in those targets and their dependencies.
+
+local prev="$words[CURRENT-1]" file expl tmp is_gnu dir incl match
+local -A TARGETS VARIABLES
expandVars() {
- local open close var val tmp=$2 ret=$2
- if (( $1 == 0 )); then
- return
- fi
- while :; do
- var=${tmp#*\$}
- if [[ $var != $tmp ]]; then
- tmp=$var
- case $var in
- (\(*)
- open='('
- close=')'
- ;;
- ({*)
- open='{'
- close='}'
- ;;
- ([[:alpha:]]*)
- open=''
- close=''
- var=${(s::)var[1]}
- ;;
- (\$*)
- # avoid parsing second $ in $$
- tmp=${tmp#\$}
- ;&
- (*)
- continue
- ;;
- esac
- if [[ $open != '' ]]; then
- var=${var#$open}
+ local open close var val front ret tmp=$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}\$$(expandVars ${tmp#\$})"
+ return
+ ;;
+
+ (*) # Nothing left to substitute.
+ print -- $tmp
+ return
+ ;;
+ esac
+
+ if [[ -n $open ]]
+ then
+ var=${tmp#$open}
var=${var%%$close*}
- fi
- case $var in
- ([[:alnum:]_]#)
- val=${(P)var}
- val=$(expandVars $(($1 - 1)) $val)
- ret=${ret//\$$open$var$close/$val}
- ;;
- esac
- else
- print -- ${ret//\$\$/\$}
- return
fi
- done
-}
-# parseMakefile only runs inside $(...), so it doesn't matter that
-# it pollutes the global namespace, setting zsh variables to
-# make variables. The difficult case is where a make variable
-# is special in zsh; we use local -h to hide those. This
-# isn't a complete solution since it means variables defined in
-# included Makefiles are undefined before returning to the parent.
-parseMakefile() {
- local input var val TAB=$'\t' dir=$1
-
- while read input; do
- case "$input " in
- ([[:alnum:]][[:alnum:]_]#[ $TAB]#=*)
- var=${input%%[ $TAB]#=*}
- val=${input#*=}
- val=${val##[ $TAB]#}
- [[ ${(tP)var} = *special ]] && local -h $var
- eval $var=\$val
- ;;
- ([[:alnum:]][[:alnum:]_]#[ $TAB]#:=*)
- var=${input%%[ $TAB]#:=*}
- val=${input#*=}
- val=${val##[ $TAB]#}
- val=$(expandVars 10 $val)
- [[ ${(tP)var} = *special ]] && local -h $var
- eval $var=\$val
- ;;
- ([[:alnum:]][^$TAB:=]#:[^=]*)
- input=${input%%:*}
- print $(expandVars 10 $input)
- ;;
- (${~incl} *)
- local f=${input##${~incl} ##}
- if [[ $incl = '.include' ]]; then
- f=${f#[\"<]}
- f=${f%[\">]}
- fi
- f=$(expandVars 10 $f)
- case $f in
- (/*) ;;
- (*) f=$dir/$f ;;
- esac
- if [ -r $f ]; then
- parseMakefile ${f%%/[^/]##} < $f
- fi
- ;;
+ case $var in
+ ([[:alnum:]_]#)
+ val=${VARIABLES[$var]}
+ ret=${ret//\$$open$var$close/$val}
+ ;;
+
+ (*) # Improper variable name. No replacement. I'm not sure if this is desired behavior.
+ front+="\$$open$var$close"
+ ret=${ret/\$$open$var$close/}
+ ;;
esac
- done
+
+ print -- "${front}$(expandVars ${ret})"
+}
+
+parseMakefile () {
+ local input var val target dep TAB=$'\t' dir=$1 tmp
+
+ while read input
+ do
+ case "$input " in
+ # VARIABLE = value
+ ([[:alnum:]][[:alnum:]_]#[ $TAB]#=*)
+ var=${input%%[ $TAB]#=*}
+ val=${input#*=}
+ val=${val##[ $TAB]#}
+ VARIABLES[$var]=$val
+ ;;
+
+ # VARIABLE := value
+ # Evaluated immediately
+ ([[:alnum:]][[:alnum:]_]#[ $TAB]#:=*)
+ var=${input%%[ $TAB]#:=*}
+ val=${input#*=}
+ val=${val##[ $TAB]#}
+ val=$(expandVars $val)
+ VARIABLES[$var]=$val
+ ;;
+
+ # TARGET: dependencies
+ # TARGET1 TARGET2 TARGET3: dependencies
+ ([[:alnum:]][^$TAB:=]#:[^=]*)
+ input=$(expandVars $input)
+ target=${input%%:*}
+ dep=${input#*:}
+ dep=${(z)dep}
+ dep="$dep"
+ for tmp in ${(z)target}
+ do
+ TARGETS[$tmp]=$dep
+ done
+ ;;
+
+ # Include another makefile
+ (${~incl} *)
+ local f=${input##${~incl} ##}
+ if [[ $incl == '.include' ]]
+ then
+ f=${f#[\"<]}
+ f=${f%[\">]}
+ fi
+ f=$(expandVars $f)
+ case $f in
+ (/*) ;;
+ (*) f=$dir/$f ;;
+ esac
+
+ if [[ -r $f ]]
+ then
+ parseMakefile ${f%%/[^/]##} < $f
+ fi
+ ;;
+ esac
+ done
}
findBasedir () {
- local file index basedir
- basedir=$PWD
- for ((index=0; index<$#@; index++)); do
- if [[ $@[index] = -C ]]; then
- file=${~@[index+1]};
- if [[ -z $file ]]; then
- # make returns with an error if an empty arg is given
- # even if the concatenated path is a valid directory
- return
- elif [[ $file = /* ]]; then
- # Absolute path, replace base directory
- basedir=$file
- else
- # Relative, concatenate path
- basedir=$basedir/$file
- fi
- fi
- done
- print -- $basedir
+ local file index basedir
+ basedir=$PWD
+ for (( index=0; index < $#@; index++ ))
+ do
+ if [[ $@[index] == -C ]]
+ then
+ file=${~@[index+1]};
+ if [[ -z $file ]]
+ then
+ # make returns with an error if an empty arg is given
+ # even if the concatenated path is a valid directory
+ return
+ elif [[ $file == /* ]]
+ then
+ # Absolute path, replace base directory
+ basedir=$file
+ else
+ # Relative, concatenate path
+ basedir=$basedir/$file
+ fi
+ fi
+ done
+ print -- $basedir
}
_pick_variant -r is_gnu gnu=GNU unix -v -f
-if [[ $is_gnu = gnu ]]; then
- incl="(-|)include"
+if [[ $is_gnu == gnu ]]
+then
+ incl="(-|)include"
else
- incl=.include
+ incl=.include
fi
-if [[ "$prev" = -[CI] ]]; then
- _files -W ${(q)$(findBasedir ${words[1,CURRENT-1]})} -/
-elif [[ "$prev" = -[foW] ]]; then
- _files -W ${(q)$(findBasedir $words)}
+
+if [[ "$prev" == -[CI] ]]
+then
+ _files -W ${(q)$(findBasedir ${words[1,CURRENT-1]})} -/
+elif [[ "$prev" == -[foW] ]]
+then
+ _files -W ${(q)$(findBasedir $words)}
else
- file="$words[(I)-f]"
- if (( file )); then
- file=${~words[file+1]}
- [[ $file = [^/]* ]] && file=${(q)$(findBasedir $words)}/$file
- [[ -r $file ]] || file=
- else
- local basedir
- basedir=${(q)$(findBasedir $words)}
- if [[ $is_gnu = gnu && -r $basedir/GNUmakefile ]]; then
- file=$basedir/GNUmakefile
- elif [[ -r $basedir/makefile ]]; then
- file=$basedir/makefile
- elif [[ -r $basedir/Makefile ]]; then
- file=$basedir/Makefile
- else
- file=''
- fi
- fi
-
- if [[ -n "$file" ]] && _tags targets; then
- if [[ $is_gnu = gnu ]] &&
- zstyle -t ":completion:${curcontext}:targets" call-command; then
- tmp=( $(_call_program targets "$words[1]" -nsp --no-print-directory -f "$file" .PHONY 2> /dev/null | parseMakefile $PWD) )
- else
- tmp=( $(parseMakefile $PWD < $file) )
- fi
- _wanted targets expl 'make target' compadd -a tmp && return 0
- fi
- compstate[parameter]="${PREFIX%%\=*}"
- compset -P 1 '*='
- _value "$@"
+ file="$words[(I)-f]"
+ if (( file ))
+ then
+ file=${~words[file+1]}
+ [[ $file == [^/]* ]] && file=${(q)$(findBasedir $words)}/$file
+ [[ -r $file ]] || file=
+ else
+ local basedir
+ basedir=${(q)$(findBasedir $words)}
+ if [[ $is_gnu == gnu && -r $basedir/GNUmakefile ]]
+ then
+ file=$basedir/GNUmakefile
+ elif [[ -r $basedir/makefile ]]
+ then
+ file=$basedir/makefile
+ elif [[ -r $basedir/Makefile ]]
+ then
+ file=$basedir/Makefile
+ else
+ file=''
+ fi
+ fi
+
+ if [[ -n "$file" ]]
+ then
+ if [[ $is_gnu == gnu ]] && zstyle -t ":completion:${curcontext}:targets" call-command
+ then
+ parseMakefile $PWD < <(_call_program targets "$words[1]" -nsp --no-print-directory -f "$file" .PHONY 2> /dev/null)
+ else
+ parseMakefile $PWD < $file
+ fi
+ fi
+
+ if [[ $PREFIX == (#b)([^=]##)'='* ]] && [[ -n ${${(k)VARIABLES}[(r)${match[1]}]} ]]
+ then
+ _message 'override make variable'
+ else
+ _tags targets variables
+ while _tags
+ do
+ _requested targets expl 'make targets' \
+ compadd -- ${(k)TARGETS}
+ _requested variables expl 'make variables' \
+ compadd -S '=' -- ${(k)VARIABLES}
+ done
+ fi
+
+ # These are left over from the old completion. I'm not sure what they do.
+ #compstate[parameter]="${PREFIX%%\=*}"
+ #compset -P 1 '*='
+ #_value "$@"
fi