mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-30 17:50:58 +01:00 
			
		
		
		
	_call_program and '_arguments --' will call _comp_locale before calling external command for easier analysis of the output. This is disabled by passing an option '-l'.
		
			
				
	
	
		
			587 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			587 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| #autoload
 | |
| 
 | |
| # Complete the arguments of the current command according to the
 | |
| # descriptions given as arguments to this function.
 | |
| 
 | |
| local long cmd="$words[1]" descr odescr mesg subopts opt opt2 usecc autod
 | |
| local oldcontext="$curcontext" hasopts rawret optarg singopt alwopt
 | |
| local setnormarg start rest
 | |
| local -a match mbegin mend
 | |
| 
 | |
| subopts=()
 | |
| singopt=()
 | |
| while [[ "$1" = -([AMO]*|[CRSWnsw]) ]]; do
 | |
|   case "$1" in
 | |
|   -C)  usecc=yes; shift ;;
 | |
|   -O)  subopts=( "${(@P)2}" ); shift 2 ;;
 | |
|   -O*) subopts=( "${(@P)${1[3,-1]}}" ); shift ;;
 | |
|   -R)  rawret=yes; shift;;
 | |
|   -n)  setnormarg=yes; NORMARG=-1; shift;;
 | |
|   -w)  optarg=yes; shift;;
 | |
|   -W)  alwopt=arg; shift;;
 | |
|   -[Ss])  singopt+=( $1 ); shift;;
 | |
|   -[AM])  singopt+=( $1 $2 ); shift 2 ;;
 | |
|   -[AM]*) singopt+=( $1 ); shift ;;
 | |
|   esac
 | |
| done
 | |
| 
 | |
| [[ $1 = ':' ]] && shift
 | |
| singopt+=( ':' )  # always end with ':' to indicate the end of options
 | |
| 
 | |
| [[ "$PREFIX" = [-+] ]] && alwopt=arg
 | |
| 
 | |
| long=$argv[(I)--]
 | |
| if (( long )); then
 | |
|   local name tmp tmpargv
 | |
| 
 | |
|   tmpargv=( "${(@)argv[1,long-1]}" )  # optspec's before --, if any
 | |
| 
 | |
|   name=${~words[1]} 2>/dev/null
 | |
|   [[ "$name" = [^/]*/* ]] && name="$PWD/$name"
 | |
| 
 | |
|   name="_args_cache_${name}"
 | |
|   name="${name//[^a-zA-Z0-9_]/_}"
 | |
| 
 | |
|   if (( ! ${(P)+name} )); then
 | |
|     local iopts sopts lflag pattern tmpo dir cur cache
 | |
|     typeset -Ua lopts
 | |
| 
 | |
|     cache=()
 | |
| 
 | |
|     # We have to build a new long-option cache, get the `-i' and
 | |
|     # `-s' options.
 | |
| 
 | |
|     set -- "${(@)argv[long+1,-1]}"
 | |
| 
 | |
|     iopts=()
 | |
|     sopts=()
 | |
|     while [[ "$1" = -[lis]* ]]; do
 | |
|       if [[ "$1" = -l ]]; then
 | |
| 	lflag='-l'
 | |
| 	shift
 | |
| 	continue
 | |
|       fi
 | |
|       if [[ "$1" = -??* ]]; then
 | |
|         tmp="${1[3,-1]}"
 | |
|         cur=1
 | |
|       else
 | |
|         tmp="$2"
 | |
| 	cur=2
 | |
|       fi
 | |
|       if [[ "$tmp[1]" = '(' ]]; then
 | |
| 	tmp=( ${=tmp[2,-2]} )
 | |
|       else
 | |
| 	tmp=( "${(@P)tmp}" )
 | |
|       fi
 | |
|       if [[ "$1" = -i* ]]; then
 | |
|         iopts+=( "$tmp[@]" )
 | |
|       else
 | |
|         sopts+=( "$tmp[@]" )
 | |
|       fi
 | |
|       shift cur
 | |
|     done
 | |
| 
 | |
|     # Now get the long option names by calling the command with `--help'.
 | |
|     # The parameter expansion trickery first gets the lines as separate
 | |
|     # array elements. Then we select all lines whose first non-blank
 | |
|     # character is a hyphen. Since some commands document more than one
 | |
|     # option per line, separated by commas, we convert commas into
 | |
|     # newlines and then split the result again at newlines after joining 
 | |
|     # the old array elements with newlines between them. Then we select
 | |
|     # those elements that start with two hyphens, remove anything up to
 | |
|     # those hyphens and anything from the space or tab after the
 | |
|     # option up to the end.
 | |
| 
 | |
|    tmp=()
 | |
|    _call_program $lflag options ${~words[1]} --help 2>&1 |
 | |
|      while IFS= read -r opt; do
 | |
|      if (( ${#tmp} )); then
 | |
|        # Previous line had no comment.  Is the current one suitable?
 | |
|        # It's hard to be sure, but if it there was nothing on the
 | |
|        # previous line and the current one is indented more than
 | |
|        # a couple of spaces (and isn't completely whitespace or punctuation)
 | |
|        # there's a pretty good chance.
 | |
|        if [[ $opt = [[:space:]][[:space:]][[:space:]]*[[:alpha:]]* ]]; then
 | |
| 	 # Assume so.
 | |
| 	 opt=${opt##[[:space:]]##}
 | |
| 	 # Same substitution as below.
 | |
| 	 lopts+=("${^tmp[@]}":${${${opt//:/-}//\[/(}//\]/)})
 | |
| 	 tmp=()
 | |
| 	 # Finished with this line.
 | |
| 	 continue
 | |
|        else
 | |
| 	 # Still no comment, add the previous options anyway.
 | |
|          # Add a ':' after the option anyways, to make the matching of
 | |
|          # the options lateron work as intended.
 | |
|          # It will be removed again later.
 | |
| 	 lopts+=("${^tmp[@]}":)
 | |
| 	 tmp=()
 | |
|        fi
 | |
|      fi
 | |
|      while [[ $opt = [,[:space:]]#(#b)(-[^,[:space:]]#)(*) ]]; do
 | |
|        # We used to remove the brackets from "[=STUFF]",
 | |
|        # but later the code appears to handle it with the brackets
 | |
|        # present.  Maybe the problem was that the intervening code
 | |
|        # didn't.  If it's buggy without removing them, the problem
 | |
|        # probably is later, not here.
 | |
|        start=${match[1]}
 | |
|        rest=${match[2]}
 | |
|        if [[ -z ${tmp[(r)${start%%[^a-zA-Z0-9_-]#}]} ]]; then
 | |
| 	 # variant syntax seen in fetchmail:
 | |
| 	 # --[fetch]all  means --fetchall or --all.
 | |
| 	 # maybe needs to be more general
 | |
| 	 if [[ $start = (#b)(*)\[(*)\](*) ]]; then
 | |
| 	   tmp+=("${match[1]}${match[2]}${match[3]}" "${match[1]}${match[3]}")
 | |
| 	 else
 | |
| 	   tmp+=($start)
 | |
| 	 fi
 | |
|        fi
 | |
|        opt=$rest
 | |
|      done
 | |
|      # If there's left over text, assume it's a description; it
 | |
|      # may be truncated but if it's too long it's no use anyway.
 | |
|      # There's one hiccup: we sometimes get descriptions like
 | |
|      # --foo fooarg   Do some foo stuff with foo arg
 | |
|      # and we need to remove fooarg.  Use whitespace for hints.
 | |
|      opt=${opt## [^[:space:]]##  }
 | |
|      opt=${opt##[[:space:]]##}
 | |
|      if [[ -n $opt ]]; then
 | |
|        # Add description after a ":", converting any : in the description
 | |
|        # to a -.  Use RCQUOTES to append this to all versions of the option.
 | |
|        lopts+=("${^tmp[@]}":${${${opt//:/-}//\[/(}//\]/)})
 | |
|        tmp=()
 | |
|        # If there's no comment, we'll see if there's one on the
 | |
|        # next line.
 | |
|      fi
 | |
|    done
 | |
|    # Tidy up any remaining uncommented options.
 | |
|    if (( ${#tmp} )); then
 | |
|      lopts+=("${^tmp[@]}":)
 | |
|    fi
 | |
| 
 | |
|     # Remove options also described by user-defined specs.
 | |
| 
 | |
|     tmp=()
 | |
|     # Ignore any argument and description information when searching
 | |
|     # the long options array here and below.
 | |
|     for opt in "${(@)${(@)lopts:#--}%%[\[:=]*}"; do
 | |
| 
 | |
|       # Using (( ... )) gives a parse error.
 | |
| 
 | |
|       let "$tmpargv[(I)(|\([^\)]#\))(|\*)${opt}(|[-+]|=(|-))(|\[*\])(|:*)]" ||
 | |
|           tmp+=( "$lopts[(r)$opt(|[\[:=]*)]" )
 | |
|     done
 | |
|     lopts=( "$tmp[@]" )
 | |
| 
 | |
|     # Now remove all ignored options ...
 | |
| 
 | |
|     while (( $#iopts )); do
 | |
|       lopts=( ${lopts:#$~iopts[1](|[\[:=]*)} )
 | |
|       shift iopts
 | |
|     done
 | |
| 
 | |
|     # ... and add "same" options
 | |
| 
 | |
|     while (( $#sopts )); do
 | |
|       # This implements adding things like --disable-* based
 | |
|       # on the existence of --enable-*.
 | |
|       # TODO: there's no anchoring here, is that correct?
 | |
|       # If it's not, careful with the [\[:=]* stuff.
 | |
|       lopts+=( ${lopts/$~sopts[1]/$sopts[2]} )
 | |
|       shift 2 sopts
 | |
|     done
 | |
| 
 | |
|     # Then we walk through the descriptions plus a few builtin ones.
 | |
|     # The last one matches all options; the `special' description and action
 | |
|     # makes those options be completed without an argument description.
 | |
| 
 | |
|     argv+=(
 | |
|       '*=FILE*:file:_files'
 | |
|       '*=(DIR|PATH)*:directory:_files -/'
 | |
|       '*=*:=: '
 | |
|       '*: :  '
 | |
|     )
 | |
| 
 | |
|     while (( $# )); do
 | |
| 
 | |
|       # First, we get the pattern and the action to use and take them
 | |
|       # from the positional parameters.
 | |
| 
 | |
|       # This is the first bit of the arguments in the special form
 | |
|       # for converting --help texts, taking account of any quoting
 | |
|       # of colons.
 | |
|       pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
 | |
|       # Any action specifications that go with it.
 | |
|       descr="${1#${pattern}}"
 | |
|       if [[ "$pattern" = *\(-\) ]]; then
 | |
| 	# This is the special form to disallow arguments
 | |
| 	# in the next word.
 | |
|         pattern="$pattern[1,-4]"
 | |
| 	dir=-
 | |
|       else
 | |
|         dir=
 | |
|       fi
 | |
|       shift
 | |
| 
 | |
|       # We get all options matching the pattern and take them from the
 | |
|       # list we have built. If no option matches the pattern, we
 | |
|       # continue with the next.
 | |
| 
 | |
|       # Ignore :descriptions at the ends of lopts for matching this;
 | |
|       # they aren't in the patterns.
 | |
|       tmp=("${(@M)lopts:##$~pattern:*}")
 | |
|       lopts=("${(@)lopts:##$~pattern:*}")
 | |
| 
 | |
|       (( $#tmp )) || continue
 | |
| 
 | |
|       opt=''
 | |
| 
 | |
|       # Clean suffix ':' added earlier
 | |
|       tmp=("${(@)tmp%:}")
 | |
| 
 | |
|       # If there are option strings with a `[=', we take these to get an
 | |
|       # optional argument.
 | |
| 
 | |
|       tmpo=("${(@M)tmp:#[^:]##\[\=*}")
 | |
|       if (( $#tmpo )); then
 | |
|         tmp=("${(@)tmp:#[^:]##\[\=*}")
 | |
| 
 | |
| 	for opt in "$tmpo[@]"; do
 | |
| 	  # Look for --option:description and turn it into
 | |
| 	  # --option[description].  We didn't do that above
 | |
| 	  # since it could get confused with the [=ARG] stuff.
 | |
| 	  if [[ $opt = (#b)(*):([^:]#) ]]; then
 | |
| 	    opt=$match[1]
 | |
| 	    odescr="[${match[2]}]"
 | |
| 	  else
 | |
| 	    odescr=
 | |
| 	  fi
 | |
| 	  if [[ $opt = (#b)(*)\[\=* ]]; then
 | |
| 	    opt2=${${match[1]}//[^a-zA-Z0-9_-]}=-${dir}${odescr}
 | |
| 	  else
 | |
| 	    opt2=${${opt}//[^a-zA-Z0-9_-]}=${dir}${odescr}
 | |
| 	  fi
 | |
| 	  if [[ "$descr" = :\=* ]]; then
 | |
| 	    cache+=( "${opt2}::${(L)${opt%\]}#*\=}: " )
 | |
| 	  elif [[ "$descr" = ::* ]]; then
 | |
| 	    cache+=( "${opt2}${descr}" )
 | |
| 	  else
 | |
| 	    cache+=( "${opt2}:${descr}" )
 | |
| 	  fi
 | |
| 	done
 | |
|       fi
 | |
| 
 | |
|       # Descriptions with `=': mandatory argument.
 | |
|       # Basically the same as the foregoing.
 | |
|       # TODO: could they be combined?
 | |
| 
 | |
|       tmpo=("${(@M)tmp:#[^:]##\=*}")
 | |
|       if (( $#tmpo )); then
 | |
|         tmp=("${(@)tmp:#[^:]##\=*}")
 | |
| 
 | |
| 	for opt in "$tmpo[@]"; do
 | |
| 	  if [[ $opt = (#b)(*):([^:]#) ]]; then
 | |
| 	    opt=$match[1]
 | |
| 	    odescr="[${match[2]}]"
 | |
| 	  else
 | |
| 	    odescr=
 | |
| 	  fi
 | |
| 	  opt2="${${opt%%\=*}//[^a-zA-Z0-9_-]}=${dir}${odescr}"
 | |
| 	  if [[ "$descr" = :\=* ]]; then
 | |
| 	    cache+=( "${opt2}:${(L)${opt%\]}#*\=}: " )
 | |
| 	  else
 | |
| 	    cache+=( "${opt2}${descr}" )
 | |
| 	  fi
 | |
| 	done
 | |
|       fi
 | |
| 
 | |
|       # Everything else is just added as an option without arguments or
 | |
|       # as described by $descr.
 | |
| 
 | |
|       if (( $#tmp )); then
 | |
|         tmp=(
 | |
| 	  # commands with a description of the option (as opposed
 | |
| 	  # to the argument, which is what descr contains): needs to be
 | |
| 	  # "option[description]".
 | |
| 	  # Careful: \[ on RHS of substitution keeps the backslash,
 | |
| 	  # I discovered after about half an hour, so don't do that.
 | |
| 	  "${(@)^${(@)tmp:#^*:*}//:/[}]"
 | |
| 	  # commands with no description
 | |
| 	  "${(@)${(@)tmp:#*:*}//[^a-zA-Z0-9_-]}")
 | |
|         if [[ -n "$descr" && "$descr" != ': :  ' ]]; then
 | |
| 	  cache+=( "${(@)^tmp}${descr}" )
 | |
|         else
 | |
| 	  cache+=( "$tmp[@]" )
 | |
|         fi
 | |
|       fi
 | |
|     done
 | |
|     set -A "$name" "${(@)cache:# #}"
 | |
|   fi
 | |
|   set -- "$tmpargv[@]" "${(@P)name}"
 | |
| fi
 | |
| 
 | |
| zstyle -s ":completion:${curcontext}:options" auto-description autod
 | |
| 
 | |
| if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then
 | |
|   local action noargs aret expl local tried ret=1
 | |
|   local next direct odirect equal single matcher matched ws tmp1 tmp2 tmp3
 | |
|   local opts subc tc prefix suffix descrs actions subcs anum
 | |
|   local origpre="$PREFIX" origipre="$IPREFIX" nm="$compstate[nmatches]"
 | |
| 
 | |
|   if comparguments -D descrs actions subcs; then
 | |
|     if comparguments -O next direct odirect equal; then
 | |
|       opts=yes
 | |
|       _tags "$subcs[@]" options
 | |
|     else
 | |
|       _tags "$subcs[@]"
 | |
|     fi
 | |
|   else
 | |
|     if comparguments -a; then
 | |
|       noargs='no more arguments'
 | |
|     else
 | |
|       noargs='no arguments'
 | |
|     fi
 | |
|     if comparguments -O next direct odirect equal; then
 | |
|       opts=yes
 | |
|       _tags options
 | |
|     elif [[ $? -eq 2 ]]; then
 | |
|         compadd -Q - "${PREFIX}${SUFFIX}"
 | |
|         return 0
 | |
|     else
 | |
|       _message "$noargs"
 | |
|       return 1
 | |
|     fi
 | |
|   fi
 | |
| 
 | |
|   comparguments -M matcher
 | |
| 
 | |
|   context=()
 | |
|   state=()
 | |
|   state_descr=()
 | |
| 
 | |
|   while true; do
 | |
|     while _tags; do
 | |
|       anum=1
 | |
|       if [[ -z "$tried" ]]; then
 | |
|         while [[ anum -le  $#descrs ]]; do
 | |
| 
 | |
| 	  action="$actions[anum]"
 | |
| 	  descr="$descrs[anum]"
 | |
| 	  subc="$subcs[anum++]"
 | |
| 
 | |
| 	  if [[ $subc = argument* && -n $setnormarg ]]; then
 | |
| 	    comparguments -n NORMARG
 | |
| 	  fi
 | |
| 
 | |
|           if [[ -n "$matched" ]] || _requested "$subc"; then
 | |
| 
 | |
|             curcontext="${oldcontext%:*}:$subc"
 | |
| 
 | |
|             _description "$subc" expl "$descr"
 | |
| 
 | |
|             if [[ "$action" = \=\ * ]]; then
 | |
|               action="$action[3,-1]"
 | |
|               words=( "$subc" "$words[@]" )
 | |
| 	      (( CURRENT++ ))
 | |
|             fi
 | |
| 
 | |
|             if [[ "$action" = -\>* ]]; then
 | |
| 	      action="${${action[3,-1]##[ 	]#}%%[ 	]#}"
 | |
| 	      if (( ! $state[(I)$action] )); then
 | |
|                 comparguments -W line opt_args
 | |
|                 state+=( "$action" )
 | |
|                 state_descr+=( "$descr" )
 | |
| 	        if [[ -n "$usecc" ]]; then
 | |
| 	          curcontext="${oldcontext%:*}:$subc"
 | |
| 	        else
 | |
| 	          context+=( "$subc" )
 | |
| 	        fi
 | |
|                 compstate[restore]=''
 | |
|                 aret=yes
 | |
|               fi
 | |
|             else
 | |
|               if [[ -z "$local" ]]; then
 | |
|                 local line
 | |
|                 typeset -A opt_args
 | |
|                 local=yes
 | |
|               fi
 | |
| 
 | |
|               comparguments -W line opt_args
 | |
| 
 | |
|               if [[ "$action" = \ # ]]; then
 | |
| 
 | |
|                 # An empty action means that we should just display a message.
 | |
| 
 | |
| 	        _message -e "$subc" "$descr"
 | |
| 	        mesg=yes
 | |
| 	        tried=yes
 | |
|                 alwopt=${alwopt:-yes}
 | |
|               elif [[ "$action" = \(\(*\)\) ]]; then
 | |
| 
 | |
|                 # ((...)) contains literal strings with descriptions.
 | |
| 
 | |
|                 eval ws\=\( "${action[3,-3]}" \)
 | |
| 
 | |
|                 _describe -t "$subc" "$descr" ws -M "$matcher" "$subopts[@]" ||
 | |
|                     alwopt=${alwopt:-yes}
 | |
| 	        tried=yes
 | |
| 
 | |
|               elif [[ "$action" = \(*\) ]]; then
 | |
| 
 | |
|                 # Anything inside `(...)' is added directly.
 | |
| 
 | |
|                 eval ws\=\( "${action[2,-2]}" \)
 | |
| 
 | |
|                 _all_labels "$subc" expl "$descr" compadd "$subopts[@]" -a - ws ||
 | |
|                     alwopt=${alwopt:-yes}
 | |
| 	        tried=yes
 | |
|               elif [[ "$action" = \{*\} ]]; then
 | |
| 
 | |
|                 # A string in braces is evaluated.
 | |
| 
 | |
|                 while _next_label "$subc" expl "$descr"; do
 | |
|                   eval "$action[2,-2]" && ret=0
 | |
|                 done
 | |
|                 (( ret )) && alwopt=${alwopt:-yes}
 | |
| 	        tried=yes
 | |
|               elif [[ "$action" = \ * ]]; then
 | |
| 
 | |
|                 # If the action starts with a space, we just call it.
 | |
| 
 | |
| 	        eval "action=( $action )"
 | |
|                 while _next_label "$subc" expl "$descr"; do
 | |
|                   "$action[@]" && ret=0
 | |
|                 done
 | |
|                 (( ret )) && alwopt=${alwopt:-yes}
 | |
| 	        tried=yes
 | |
|               else
 | |
| 
 | |
|                 # Otherwise we call it with the description-arguments.
 | |
| 
 | |
| 	        eval "action=( $action )"
 | |
|                 while _next_label "$subc" expl "$descr"; do
 | |
|                   "$action[1]" "$subopts[@]" "$expl[@]" "${(@)action[2,-1]}" && ret=0
 | |
| 	        done
 | |
|                 (( ret )) && alwopt=${alwopt:-yes}
 | |
| 	        tried=yes
 | |
|               fi
 | |
|             fi
 | |
|           fi
 | |
|         done
 | |
|       fi
 | |
|       if _requested options &&
 | |
|          [[ -z "$hasopts" &&
 | |
|             -z "$matched" &&
 | |
|             ( -z "$aret" || "$PREFIX" = "$origpre" ) ]] &&
 | |
|           { ! zstyle -T ":completion:${oldcontext%:*}:options" prefix-needed ||
 | |
|             [[ "$origpre" = [-+]* || -z "$aret$mesg$tried" ]] } ; then
 | |
| 	local prevpre="$PREFIX" previpre="$IPREFIX" prevcontext="$curcontext"
 | |
| 
 | |
|         curcontext="${oldcontext%:*}:options"
 | |
| 
 | |
| 	hasopts=yes
 | |
| 
 | |
| 	PREFIX="$origpre"
 | |
| 	IPREFIX="$origipre"
 | |
| 
 | |
|         if [[ -z "$alwopt" || -z "$tried" || "$alwopt" = arg ]] &&
 | |
|            comparguments -s single; then
 | |
| 
 | |
|           if [[ "$single" = direct ]]; then
 | |
|             _all_labels options expl option \
 | |
| 	        compadd -QS '' - "${PREFIX}${SUFFIX}"
 | |
|           elif [[ -z "$optarg" && "$single" = next ]]; then
 | |
|             _all_labels options expl option \
 | |
| 	        compadd -Q - "${PREFIX}${SUFFIX}"
 | |
|           elif [[ "$single" = equal ]]; then
 | |
|             _all_labels options expl option \
 | |
| 	        compadd -QqS= - "${PREFIX}${SUFFIX}"
 | |
|           else
 | |
| 
 | |
| 	    tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
 | |
| 
 | |
|             [[ "$PREFIX" = [-+]* ]] && tmp1=( "${(@M)tmp1:#${PREFIX[1]}*}" )
 | |
| 
 | |
|             [[ "$single" = next ]] &&
 | |
|                 tmp1=( "${(@)tmp1:#[-+]${PREFIX[-1]}((#e)|:*)}" )
 | |
| 
 | |
| 	    [[ "$PREFIX" != --* ]] && tmp1=( "${(@)tmp1:#--*}" )
 | |
| 	    tmp3=( "${(M@)tmp1:#[-+]?[^:]*}" )
 | |
| 	    tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
 | |
| 	    tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
 | |
| 
 | |
|             _describe -O option \
 | |
|                       tmp1 tmp2 -Q -S '' -- \
 | |
| 		      tmp3 -Q
 | |
| 
 | |
|             [[ -n "$optarg" && "$single" = next && nm -eq $compstate[nmatches] ]] &&
 | |
|                 _all_labels options expl option \
 | |
| 	            compadd -Q - "${PREFIX}${SUFFIX}"
 | |
| 
 | |
|           fi
 | |
|           single=yes
 | |
|         else
 | |
|           next+=( "$odirect[@]" )
 | |
|           _describe -O option \
 | |
|                     next -Q -M "$matcher" -- \
 | |
|                     direct -QS '' -M "$matcher" -- \
 | |
|                     equal -QqS= -M "$matcher"
 | |
|         fi
 | |
| 	PREFIX="$prevpre"
 | |
| 	IPREFIX="$previpre"
 | |
|         curcontext="$prevcontext"
 | |
|       fi
 | |
|       [[ -n "$tried" && "${${alwopt:+$origpre}:-$PREFIX}" != [-+]* ]] && break
 | |
|     done
 | |
|     if [[ -n "$opts" && -z "$aret" &&
 | |
|           -z "$matched" &&
 | |
|           ( -z "$tried" || -n "$alwopt" ) &&
 | |
|           nm -eq compstate[nmatches] ]]; then
 | |
| 
 | |
|       PREFIX="$origpre"
 | |
|       IPREFIX="$origipre"
 | |
| 
 | |
|       prefix="${PREFIX#*\=}"
 | |
|       suffix="$SUFFIX"
 | |
|       PREFIX="${PREFIX%%\=*}"
 | |
|       SUFFIX=''
 | |
| 
 | |
|       compadd -M "$matcher" -D equal - "${(@)equal%%:*}"
 | |
| 
 | |
|       if [[ $#equal -eq 1 ]]; then
 | |
|         PREFIX="$prefix"
 | |
| 	SUFFIX="$suffix"
 | |
| 	IPREFIX="${IPREFIX}${equal[1]%%:*}="
 | |
| 	matched=yes
 | |
| 
 | |
| 	comparguments -L "${equal[1]%%:*}" descrs actions subcs
 | |
| 
 | |
| 	_tags "$subcs[@]"
 | |
| 
 | |
| 	continue
 | |
|       fi
 | |
|     fi
 | |
|     break
 | |
|   done
 | |
| 
 | |
|   [[ -z "$aret" || -z "$usecc" ]] && curcontext="$oldcontext"
 | |
| 
 | |
|   if [[ -n "$aret" ]]; then
 | |
|     [[ -n $rawret ]] && return 300
 | |
| 
 | |
| ### Returning non-zero would allow the calling function to add its own
 | |
| ### completions if we generated only options and have to use a ->state
 | |
| ### action.  But if that then doesn't generate matches, the calling
 | |
| ### function's return value would be wrong unless it compares
 | |
| ### $compstate[nmatches] to its previous value.  Ugly.
 | |
| ###
 | |
| ###    return 1
 | |
|   else
 | |
|     [[ -n "$noargs" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
 | |
|   fi
 | |
|   # Set the return value.
 | |
| 
 | |
|   [[ nm -ne "$compstate[nmatches]" ]]
 | |
| else
 | |
|   return 1
 | |
| fi
 |