about summary refs log tree commit diff
path: root/Completion/Base
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Base')
-rw-r--r--Completion/Base/_arguments285
1 files changed, 196 insertions, 89 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 5925cbc42..c8dceed26 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -5,22 +5,22 @@
 
 setopt localoptions extendedglob
 
-local args rest ws cur nth def nm expl descr action opt arg tmp
-local single uns ret=1 soptseq soptseq1 sopts prefix line
-local beg optbeg argbeg nargbeg inopt inrest fromrest
+local args rest ws cur nth def nm expl descr action opt arg tmp xor
+local single uns ret=1 soptseq soptseq1 sopts prefix _line odescr
+local beg optbeg argbeg nargbeg inopt inrest fromrest cmd="$words[1]"
+local matched curopt
 
 # Associative arrays used to collect information about the options.
 
-typeset -A opts dopts odopts
-typeset -A oneshot
+typeset -A opts dopts odopts xors _options
 
 # Fill the cache if we were called with different arguments.
 
 if [[ "$*" != "$_args_cache_descr" ]]; then
   _args_cache_descr="$*"
 
-  unset _args_cache_{opts,dopts,odopts,oneshot}
-  typeset -gA _args_cache_{opts,dopts,odopts,oneshot}
+  unset _args_cache_{opts,dopts,odopts,odescr,xors}
+  typeset -gA _args_cache_{opts,dopts,odopts,xors}
 
   unset _args_cache_{long,longcmd,single,rest,args,sopts,soptseq,soptseq1}
 
@@ -182,10 +182,29 @@ if [[ "$*" != "$_args_cache_descr" ]]; then
 
   # Now parse the arguments...
 
+  odescr=()
   args=()
   nth=1
   while (( $# )); do
 
+    descr=''
+    xor=''
+
+    # Get the names of other values that are mutually exclusive with
+    # this one.
+
+    if [[ "$1" = \(*\)* ]]; then
+      xor="${${1[2,-1]}%%\)*}"
+      1="${1#*\)}"
+    fi
+
+    # Get a description, if any.
+
+    if [[ "$1" = *\[*\](|:*) ]]; then
+      descr="${${1#*\[}%%\]*}"
+      1="${1/\[$descr\]}"
+    fi
+
     # Description for both the `-foo' and `+foo' form?
 
     if [[ "$1" = (\*|)(-+|+-)* ]]; then
@@ -196,12 +215,10 @@ if [[ "$*" != "$_args_cache_descr" ]]; then
       if [[ "$1" = \** ]]; then
         tmp="${1[4,-1]%%:*}"
         [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]"
-        unset "_args_cache_oneshot[-$tmp]" "_args_cache_oneshot[+$tmp]"
       else
         tmp="${1[3,-1]%%:*}"
         [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]"
-        _args_cache_oneshot[-$tmp]=yes
-        _args_cache_oneshot[+$tmp]=yes
+        xor="$xor -$tmp +$tmp"
       fi
 
       # If the option name ends in a `-', the first argument comes
@@ -222,6 +239,12 @@ if [[ "$*" != "$_args_cache_descr" ]]; then
         _args_cache_opts[-$tmp]=''
         _args_cache_opts[+$tmp]=''
       fi
+
+      _args_cache_odescr=( "$_args_cache_odescr[@]" {-,+}"${tmp}:$descr" )
+      if [[ -n "$xor" ]]; then
+        _args_cache_xors[-$tmp]="${${xor##[ 	]#}%%[ 	]#}"
+        _args_cache_xors[+$tmp]="${${xor##[ 	]#}%%[ 	]#}"
+      fi
     elif [[ "$1" = (\*|)[-+]* ]]; then
 
       # With a `*' at the beginning, the option may appear more than
@@ -230,11 +253,10 @@ if [[ "$*" != "$_args_cache_descr" ]]; then
       if [[ "$1" = \** ]]; then
         tmp="${1[2,-1]%%:*}"
         [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]"
-        unset "_args_cache_oneshot[$tmp]"
       else
         tmp="${1%%:*}"
         [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]"
-        _args_cache_oneshot[$tmp]=yes
+	xor="$xor ${tmp%\=}"
       fi
 
       # If the option name ends in a `-', the first argument comes
@@ -251,6 +273,9 @@ if [[ "$*" != "$_args_cache_descr" ]]; then
       else
         _args_cache_opts[$tmp]=''
       fi
+      _args_cache_odescr=( "$_args_cache_odescr[@]" "${tmp%[-+=]}:$descr" )
+      [[ -n "$xor" ]] && 
+          _args_cache_xors[${tmp%\=}]="${${xor##[ 	]#}%%[ 	]#}"
     elif [[ "$1" = \*::* ]]; then
 
       # This is `*:...', describing `all other arguments', with argument 
@@ -306,7 +331,8 @@ rest="$_args_cache_rest"
 opts=( "${(@kv)_args_cache_opts}" )
 dopts=( "${(@kv)_args_cache_dopts}" )
 odopts=( "${(@kv)_args_cache_odopts}" )
-oneshot=( "${(@kv)_args_cache_oneshot}" )
+odescr=( "$_args_cache_odescr[@]" )
+xors=( "${(@kv)_args_cache_xors}" )
 single="$_args_cache_single"
 
 # Parse the command line...
@@ -314,7 +340,7 @@ single="$_args_cache_single"
 ws=( "${(@)words[2,-1]}" )
 cur=$(( CURRENT-2 ))
 nth=1
-line=( "$words[1]" )
+_line=( "$words[1]" )
 beg=2
 argbeg=1
 optbeg=1
@@ -324,6 +350,14 @@ nargbeg=1
 
 while [[ cur -gt 0 ]]; do
 
+  if [[ -n "$def" && -n "$curopt" ]]; then
+    if [[ -n "$_options[$curopt]" ]]; then
+      _options[$curopt]="$_options[$curopt]:${ws[1]//:/\\:}"
+    else
+      _options[$curopt]="${ws[1]//:/\\:}"
+    fi
+  fi
+
   # `def' holds the description for the option we are currently after.
   # Check if the next argument for the option is optional.
 
@@ -339,6 +373,7 @@ while [[ cur -gt 0 ]]; do
 
   if [[ "$def" = \**[^\\]:* && "$ws[1]" = ${~${(M)def#*[^\\]:}[2,-2]} ]]; then
     def=''
+    curopt=''
     shift 1 ws
     (( cur-- ))
     (( beg++ ))
@@ -353,6 +388,7 @@ while [[ cur -gt 0 ]]; do
       argbeg="$beg"
     else
       def=''
+      curopt=''
     fi
   elif [[ -z "$def" ]]; then
 
@@ -360,6 +396,7 @@ while [[ cur -gt 0 ]]; do
 
     opt=yes
     arg=yes
+    curopt=''
   fi
 
   if [[ -n "$opt" ]]; then
@@ -374,16 +411,23 @@ while [[ cur -gt 0 ]]; do
       # associative array so that we don't offer them again.
 
       def="$opts[$ws[1]]"
+      curopt="$ws[1]"
+      _options[$curopt]=''
       optbeg="$beg"
       argbeg="$beg"
       inopt=yes
-      [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]"
+      if [[ -n "$xors[$ws[1]]" ]]; then
+        odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$ws[1]]}}):*}" )
+        unset {{,d,od}opts,xors}\[${^=xors[$ws[1]]}\]
+      fi
     else
       uns=''
       if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then
 	tmp="${ws[1][1]}${ws[1][-1]}"
 	if (( $+opts[$tmp] )); then
 	  def="$opts[$tmp]"
+          curopt="$tmp"
+          _options[$curopt]=''
 	  optbeg="$beg"
 	  argbeg="$beg"
           inopt=yes
@@ -425,10 +469,15 @@ while [[ cur -gt 0 ]]; do
 
 	  opt=''
 	  def="$dopts[$tmp[1]]"
+          curopt="$tmp[1]"
+	  _options[$curopt]="${ws[1]#${tmp[1]}}"
 	  optbeg="$beg"
 	  argbeg="$beg"
 	  inopt=yes
-	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]"
+	  if [[ -n "$xors[$tmp[1]]" ]]; then
+            odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$tmp[1]]}}):*}" )
+            unset {{,d,od}opts,xors}\[${^=xors[$tmp[1]]}\]
+          fi
 	  if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then
             def="${def#?*[^\\]:*[^\\]:}"
           else
@@ -453,11 +502,28 @@ while [[ cur -gt 0 ]]; do
 	if (( $#tmp )); then
 	  opt=''
 	  def="$odopts[$tmp[1]]"
-          [[ -z "$def" ]] && def="$odopts[$tmp[1]=]"
+	  curopt="$tmp[1]"
+          if [[ -z "$def" ]]; then
+	    def="$odopts[$tmp[1]=]"
+	    if [[ "$ws[1]" = ${tmp[1]}?* ]]; then
+	      _options[$curopt]="${ws[1]#${tmp[1]}=}"
+            else
+	      _options[$curopt]=''
+	    fi
+          else
+	    if [[ "$ws[1]" = ${tmp[1]}?* ]]; then
+	      _options[$curopt]="${ws[1]#${tmp[1]}}"
+            else
+	      _options[$curopt]=''
+	    fi
+	  fi
 	  optbeg="$beg"
 	  argbeg="$beg"
 	  inopt=yes
-	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]"
+	  if [[ -n "$xors[$tmp[1]]" ]]; then
+            odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$tmp[1]]}}):*}" )
+            unset {{,d,od}opts,xors}\[${^=xors[$tmp[1]]}\]
+          fi
 
 	  # For options whose first argument *may* come after the
 	  # option, we skip over the first description only if there
@@ -481,7 +547,7 @@ while [[ cur -gt 0 ]]; do
           uns="${ws[1][2,-1]}"
 
       if [[ -n "$uns" ]]; then
-	uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}"
+        uns="${(@j::)${(v)=xors[(I)${ws[1][1]}[$uns]]}#[-+]}"
 	tmp=(
 	  "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]"
 	  "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]"
@@ -496,7 +562,7 @@ while [[ cur -gt 0 ]]; do
 
       if [[ -n "$opt" && -n "$arg" ]]; then
         def=''
-	line=( "$line[@]" "$ws[1]" )
+	_line=( "$_line[@]" "$ws[1]" )
 	[[ -n "$inopt" ]] && nargbeg=$(( beg - 1 ))
 	inopt=''
         if [[ -z "$args[nth]" && "$rest" = \*::* ]]; then
@@ -593,7 +659,7 @@ if [[ -z "$def" || "$def" = :* ]]; then
       uns="${PREFIX[2,-1]}"
 
   if [[ -n "$uns" ]]; then
-    uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}"
+    uns="${(@j::)${(v)=xors[(I)${ws[1][1]}[$uns]]}#[-+]}"
     tmp=(
       "opts[${(@)^opts[(I)${pre[1]}[$uns]]}]"
       "dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]"
@@ -657,67 +723,134 @@ while true; do
 
     _description expl "$descr"
 
-    if [[ "$action" = \ # ]]; then
+    if [[ "$action" = -\>* ]]; then
+      line=( "$_line[@]" )
+      options=( "${(@kv)_options}" )
+      state="${${action[3,-1]##[ 	]#}%%[ 	]#}"
+      compstate[restore]=''
+      return 1
+    else
+      if [[ "${(t)line}" != *local* ]]; then
+        local line
+	typeset -A options
+      fi
 
-      # An empty action means that we should just display a message.
+      line=( "$_line[@]" )
+      options=( "${(@kv)_options}" )
 
-      _message "$descr"
-      break
+      if [[ "$action" = \ # ]]; then
 
-    elif [[ "$action" = \(\(*\)\) ]]; then
+        # An empty action means that we should just display a message.
 
-      # ((...)) contains literal strings with descriptions.
+        [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX"
+        _message "$descr"
+        break
 
-      eval ws\=\( "${action[3,-3]}" \)
+      elif [[ "$action" = \(\(*\)\) ]]; then
 
-      compadd -D ws - "${(@)ws%%:*}"
+        # ((...)) contains literal strings with descriptions.
 
-      if (( $#ws )); then
-        beg=1
-        for nth in "$ws[@]"; do
-          tmp="${#nth%%:*}"
-	  [[ tmp -gt beg ]] && beg="$tmp"
-        done
-        tmp=''
-        for nth in "$ws[@]"; do
-          tmp="$tmp
-${(r:beg:: :)nth%%:*} -- ${nth#*:}"
-        done
-        tmp="$tmp[2,-1]"
-        compadd "$expl[@]" -y tmp - "${(@)ws%%:*}"
-      else
-        _message "$descr"
-      fi
-    elif [[ "$action" = \(*\) ]]; then
+        eval ws\=\( "${action[3,-3]}" \)
 
-      # Anything inside `(...)' is added directly.
+	if _display tmp ws -M 'r:|[_-]=* r:|=*'; then
+          compadd "$expl[@]" -y tmp - "${(@)ws%%:*}"
+        else
+          [[ -n "$matched" ]] && compadd -Q -S -s "$SUFFIX" - "$PREFIX"
+          _message "$descr"
+        fi
+      elif [[ "$action" = \(*\) ]]; then
 
-      compadd "$expl[@]" - ${=action[2,-2]}
-    elif [[ "$action" = \{*\} ]]; then
+        # Anything inside `(...)' is added directly.
 
-      # A string in braces is evaluated.
+        compadd "$expl[@]" - ${=action[2,-2]}
+      elif [[ "$action" = \{*\} ]]; then
 
-      eval "$action[2,-2]"
+        # A string in braces is evaluated.
 
-    elif [[ "$action" = \ * ]]; then
+        eval "$action[2,-2]"
 
-      # If the action starts with a space, we just call it.
+      elif [[ "$action" = \ * ]]; then
 
-      ${(e)=~action}
-    else
+        # If the action starts with a space, we just call it.
+
+        ${(e)=~action}
+      else
+
+        # Otherwise we call it with the description-arguments built above.
+
+        action=( $=action )
+        ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+      fi
+    fi
+  fi
 
-      # Otherwise we call it with the description-arguments built above.
+  # Probably add the option names.
+
+  if [[ -n "$opt" &&
+        ( nm -eq compstate[nmatches] ||
+          -z "$compconfig[option_prefix]" || 
+          "$compconfig[option_prefix]" = *\!${cmd}* ||
+          "$PREFIX" = [-+]* ) ]]; then
+    _description expl option
+    if [[ -n "$sopts" && -n "$PREFIX" &&
+      "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then
+      if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then
+        if [[ -n "$compconfig[describe_options]" &&
+              "$compconfig[describe_options]" != *\!${cmd}* ]]; then
+          _display tmp odescr
+        else
+          tmp="( ${(j: :)${(@)${(@M)${=:-${(k)opts} ${(k)dopts} ${(k)odopts}}:#[-+]?(|=)}#?}%=} )"
+        fi
+        compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -y tmp - \
+                "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \
+	        "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \
+	        "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" && 
+            ret=0
+      else
+        # The last option takes an argument in the next word.
 
-      action=( $=action )
-      ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+        compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - "${PREFIX}" && ret=0
+      fi
+    else
+      tmp=''
+      if [[ -n "$compconfig[describe_options]" &&
+            "$compconfig[describe_options]" != *\!${cmd}* ]]; then
+        if _display tmp odescr; then
+          if (( $#dopts )); then
+            compadd -n "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' -y tmp - \
+                    "${(@k)dopts}" && ret=0
+            compadd -n -J option -Q -M 'r:|[_-]=* r:|=*' - \
+                    "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0
+            compadd -n -J option -QqS= -M 'r:|[_-]=* r:|=*' - \
+                    "${(@k)odopts[(I)*=]%=}" && ret=0
+          elif (( ${(@k)#odopts[(I)*=]} )); then
+            compadd -n "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' -y tmp - \
+                    "${(@k)odopts[(I)*=]%=}" && ret=0
+            compadd -n -J option -Q -M 'r:|[_-]=* r:|=*' - \
+                    "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0
+          else
+            compadd -n "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -y tmp - \
+                    "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0
+          fi
+        fi
+      fi
+      if [[ -z "$tmp" ]]; then
+        compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - \
+                "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0
+        compadd "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' - \
+                "${(@k)odopts[(I)*=]%=}" && ret=0
+        compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' - \
+                "${(@k)dopts}" && ret=0
+      fi
     fi
   fi
 
-  if [[ nm -eq compstate[nmatches] && $#_args_cache_long -ne 0 &&
-        "$PREFIX" = --*=* ]]; then
+  if [[ nm -eq compstate[nmatches] && 
+        ( -z "$single" ||
+          ( $#_args_cache_long -ne 0 && "$PREFIX" = --*=* ) ) ]]; then
     local suffix
 
-    tmp=( "${(@Mk)odopts:#--[^:]#\=}" )
+    tmp=( "${(@Mk)odopts:#[^:]#\=}" )
     prefix="${PREFIX#*\=}"
     suffix="$SUFFIX"
     PREFIX="${PREFIX%%\=*}"
@@ -729,40 +862,14 @@ ${(r:beg:: :)nth%%:*} -- ${nth#*:}"
       PREFIX="$prefix"
       SUFFIX="$suffix"
       IPREFIX="$tmp[1]"
+      matched=yes
       continue
     fi
   fi
+
   break
 done
 
-# Probably add the option names.
-
-if [[ -n "$opt" &&
-      ( nm -eq compstate[nmatches] ||
-        -z "$compconfig[option_prefix]" || "$PREFIX" = [-+]* ) ]]; then
-  _description expl option
-  if [[ -n "$sopts" && -n "$PREFIX" &&
-    "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then
-    if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then
-      compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' \
-              -y "( ${(j: :)${(@)${(@M)${=:-${(k)opts} ${(k)dopts} ${(k)odopts}}:#[-+]?(|=)}#?}%=} )" - \
-              "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \
-	      "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \
-	      "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" && ret=0
-    else
-      # The last option takes an argument in the next word.
-
-      compadd "$expl[@]" -Q  -M 'r:|[_-]=* r:|=*' - "${PREFIX}" && ret=0
-    fi
-  else
-    compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - \
-            "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0
-    compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -qS= - \
-            "${(@k)odopts[(I)*=]%=}" && ret=0
-    compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' - "${(@k)dopts}" && ret=0
-  fi
-fi
-
 # Set the return value.
 
 [[ nm -ne "$compstate[nmatches]" ]]