mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-11-04 07:21:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			168 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
#compdef make gmake pmake dmake
 | 
						|
 | 
						|
local prev="$words[CURRENT-1]" file expl tmp is_gnu dir incl
 | 
						|
 | 
						|
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}
 | 
						|
		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
 | 
						|
	    ;;
 | 
						|
	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
 | 
						|
}
 | 
						|
 | 
						|
_pick_variant -r is_gnu gnu=GNU unix -v -f
 | 
						|
 | 
						|
if [[ $is_gnu = gnu ]]; then
 | 
						|
    incl="(-|)include"
 | 
						|
else
 | 
						|
    incl=.include
 | 
						|
fi
 | 
						|
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 "$@"
 | 
						|
fi
 |