Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Bug#262247: zsh: Improved make completion



On Wed, Aug 18, 2004 at 11:07:36AM -0400, Hugo Haas wrote:
> Attached is an attempt at doing this. It seems to work, though I only
> enabled it for the gnu case.

I tried your patch, and it ignored targets that had dependencies (since
it only matched a colon at the end of the line).  Here's my attempt at a
zsh-only verson of _make.  It not only follows include files, but it
expands variables too.  I tried to make it handle both gnu and non-gnu
include files, but I assume that the ".include <...>" form needs more
code to handle where the include really resides.

Since the patch was larger than the new _make script, I'm just attaching
the new _make script here.  Give it a try and see how you like it.

Also, feel free to suggest how to improve it (for instance, I'd like to
know if the eval statements can be replaced with something else).

..wayne..
#compdef make gmake pmake dmake

local prev="$words[CURRENT-1]" file expl tmp is_gnu cmdargs dir incl

expandVars() {
    local open close var val tmp=$1 ret=$1
    while :; do
	var=${tmp#*\$}
	if [[ $var != $tmp ]]; then
	    tmp=$var
	    case $var in
	    (\(*)
		open='('
		close=')'
		;;
	    ({*)
		open='{'
		close='}'
		;;
	    ([[:alnum:]]*)
		open=''
		close=''
		var=${(s::)var[1]}
		;;
	    (*)
		continue
		;;
	    esac
	    if [[ $open != '' ]]; then
		var=${var#$open}
		var=${var%%$close*}
	    fi
	    case $var in
	    ([[:alnum:]_]#)
		eval val=\${$var}
		val=$(expandVars $val)
		ret=${ret//\$$open$var$close/$val}
		;;
	    esac
	else
	    print $ret
	    return
	fi
    done
}

parseMakefile() {
    local input var val TAB=$'\t' dir=$1

    while read input; do
	case "$input " in
	([[:alnum:]][^$TAB:= ]#[ $TAB]#=*)
	    var=${input%%[ $TAB]#=*}
	    val=${input#*=}
	    val=${val##[ $TAB]#}
	    eval $var=\$val
	    ;;
	([[:alnum:]][^$TAB:= ]#[ $TAB]#:=*)
	    var=${input%%[ $TAB]#:=*}
	    val=${input#*=}
	    val=${val##[ $TAB]#}
	    val=$(expandVars $val)
	    eval $var=\$val
	    ;;
	([[:alnum:]][^$TAB:=]#:[^=]*)
	    input=${input%%:*}
	    print $(expandVars $input)
	    ;;
	($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
}

_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 -/
elif [[ "$prev" = -[foW] ]]; then
  _files
else
  file="$words[(I)-f]"
  if (( file )); then
    file="$words[file+1]"
  elif [[ -e Makefile ]]; then
    file=Makefile
  elif [[ -e makefile ]]; then
    file=makefile
  elif [[ $is_gnu = gnu && -e GNUmakefile ]]; then
    file=GNUmakefile
  else
    file=''
  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


Messages sorted by: Reverse Date, Date, Thread, Author