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/_arguments182
1 files changed, 59 insertions, 123 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 3d742f0f9..120c50934 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -6,11 +6,12 @@
 setopt localoptions extendedglob
 
 local long args rest ws cur nth def nm expl descr action opt arg tmp
-local single uns ret=1 soptseq soptseq1 sopts
+local single uns ret=1 soptseq soptseq1 sopts prefix
 
 # Associative arrays used to collect information about the options.
 
-typeset -A opts mopts dopts dmopts odopts odmopts
+typeset -A opts dopts odopts
+typeset -A oneshot
 
 # See if we are using single-letter options.
 
@@ -46,30 +47,40 @@ while (( $# )); do
       # is in the next word.
 
       if [[ "$1" = [^:]##-:* ]]; then
-        dopts[${${1%%:*}[1,-2]}]="${1#*:}"
+	tmp="${${1%%:*}[1,-2]}"
+        dopts[$tmp]="${1#*:}"
       elif [[ "$1" = [^:]##+:* ]]; then
-        odopts[${${1%%:*}[1,-2]}]="${1#*:}"
+	tmp="${${1%%:*}[1,-2]}"
+        odopts[$tmp]="${1#*:}"
       else
-        opts[${1%%:*}]="${1#*:}"
+        tmp="${1%%:*}"
+        opts[$tmp]="${1#*:}"
       fi
     else
-      opts[$1]=''
+      tmp="$1"
+      opts[$tmp]=''
     fi
+    oneshot[$tmp]=yes
   elif [[ "$1" = \*[-+]* ]]; then
 
     # The same for options that may appear more than once.
 
     if [[ "$1" = *:* ]]; then
       if [[ "$1" = [^:]##-:* ]]; then
-        dmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
+        tmp="${${1[2,-1]%%:*}[1,-2]}"
+        dopts[$tmp]="${1#*:}"
       elif [[ "$1" = [^:]##+:* ]]; then
-        odmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
+        tmp="${${1[2,-1]%%:*}[1,-2]}"
+        odopts[$tmp]="${1#*:}"
       else
-        mopts[${1[2,-1]%%:*}]="${1#*:}"
+        tmp="${1[2,-1]%%:*}"
+        opts[$tmp]="${1#*:}"
       fi
     else
-      mopts[${1[2,-1]}]=''
+      tmp="${1[2,-1]}"
+      opts[$tmp]=''
     fi
+    unset "oneshot[$tmp]"
   elif [[ "$1" = \*:* ]]; then
 
     # This is `*:...', describing `all other arguments'.
@@ -91,7 +102,7 @@ while (( $# )); do
 done
 
 if [[ -n "$single" ]]; then
-  soptseq="${(@j::)${(@M)${(@k)opts[(R)]}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)mopts[(R)]}:#[-+]?}#[-+]}"
+  soptseq="${(@j::)${(@M)${(@k)opts[(R)]}:#[-+]?}#[-+]}"
   if [[ -n "$soptseq" ]]; then
     soptseq="[$soptseq]#"
     soptseq1="$soptseq#"
@@ -99,7 +110,7 @@ if [[ -n "$single" ]]; then
     soptseq=''
     soptseq1=''
   fi
-  sopts="${(@j::)${(@M)${(@k)opts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)mopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)dopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)dmopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)odopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)odmopts}:#[-+]?}#[-+]}"
+  sopts="${(@j::)${(@M)${(@k)opts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)dopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)odopts}:#[-+]?}#[-+]}"
 else
   soptseq=''
   soptseq1=''
@@ -168,18 +179,13 @@ else
         # associative array so that we don't offer them again.
 
         def="$opts[$ws[1]]"
-        unset "opts[$ws[1]]"
-      elif (( $+mopts[$ws[1]] )); then
-        def="$mopts[$ws[1]]"
+        [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]"
       else
         uns=''
         if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then
-	  if (( $+opts[${ws[1][1]}${ws[1][-1]}] )); then
-	    def="$opts[${ws[1][1]}${ws[1][-1]}]"
-	    uns="${ws[1][2,-1]}"
-	    opt=''
-	  elif (( $+mopts[${ws[1][1]}${ws[1][-1]}] )); then
-	    def="$mopts[${ws[1][1]}${ws[1][-1]}]"
+	  tmp="${ws[1][1]}${ws[1][-1]}"
+	  if (( $+opts[$tmp] )); then
+	    def="$opts[$tmp]"
 	    uns="${ws[1][2,-1]}"
 	    opt=''
 	  fi
@@ -187,7 +193,7 @@ else
 
         # If the word is none of the simple options, test for those
         # whose first argument has to or may come directly after the
-        # option. This is done in four loops looking very much alike.
+        # option. This is done in two loops looking very much alike.
 
         if [[ -n "$opt" && $#dopts -ne 0 ]]; then
 
@@ -218,7 +224,7 @@ else
 
 	    opt=''
 	    def="$dopts[$tmp[1]]"
-	    unset "dopts[$tmp[1]]"
+	    [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]"
 	    if [[ "$def" = ?*:*:* ]]; then
               def="${def#?*:*:}"
             else
@@ -226,30 +232,6 @@ else
 	    fi
           fi
         fi
-	if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
-	  tmp=( "${(@k)dmopts}" )
-	  while (( $#tmp )); do
-            if [[ -n "$sopts" && $tmp[1] = [-+]? ]]; then
-	      if [[ "$ws[1]" = ${tmp[1][1]}${~soptseq}${tmp[1][2]}* ]]; then
-	        uns="${ws[1][2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
-		break;
-	      fi
-	    elif [[ "$ws[1]" = ${tmp[1]}* ]]; then
-	      break
-	    fi
-	    shift 1 tmp
-	  done
-
-	  if (( $#tmp )); then
-	    opt=''
-	    def="$dmopts[$tmp[1]]"
-	    if [[ "$def" = ?*:*:* ]]; then
-              def="${def#?*:*:}"
-            else
-              def=''
-            fi
-          fi
-	fi
         if [[ -n "$opt" && $#odopts -ne 0 ]]; then
 	  tmp=( "${(@k)odopts}" )
 	  while (( $#tmp )); do
@@ -267,14 +249,15 @@ else
 	  if (( $#tmp )); then
 	    opt=''
 	    def="$odopts[$tmp[1]]"
-	    unset "odopts[$tmp[1]]"
+	    [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]"
 
 	    # For options whose first argument *may* come after the
 	    # option, we skip over the first description only if there
 	    # is something after the option name on the line.
 
 	    if [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) ||
-                  ( -n "$sopts" && $tmp[1] = [-+]? && "$ws[1]" != ${tmp[1][1]}${~soptseq}${tmp[1][2]} ) ]]; then
+                  ( -n "$sopts" && ( ( $tmp[1] = [-+]? && "$ws[1]" != "${tmp[1][1]}"${~soptseq}"${tmp[1][2]}" ) ||
+		  		     ( $tmp[1] != [-+]? && "$ws[1]" != "$tmp[1]" ) ) ) ]]; then
 	      if [[ "$def" = ?*:*:* ]]; then
                 def="${def#?*:*:}"
               else
@@ -283,41 +266,16 @@ else
 	    fi
           fi
         fi
-	if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
-	  tmp=( "${(@k)odmopts}" )
-	  while (( $#tmp )); do
-            if [[ -n "$sopts" && $tmp[1] = [-+]? ]]; then
-	      if [[ "$ws[1]" = ${tmp[1][1]}${~soptseq}${tmp[1][2]}* ]]; then
-	        uns="${ws[1][2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
-		break;
-	      fi
-	    elif [[ "$ws[1]" = ${tmp[1]}* ]]; then
-	      break
-	    fi
-	    shift 1 tmp
-	  done
-
-	  if (( $#tmp )); then
-	    opt=''
-	    def="$odmopts[$tmp[1]]"
-	    if [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) ||
-                  ( -n "$sopts" && $tmp[1] = [-+]? && "$ws[1]" != ${tmp[1][1]}${~soptseq}${tmp[1][2]} ) ]]; then
-	      if [[ "$def" = ?*:*:* ]]; then
-                def="${def#?*:*:}"
-              else
-                def=''
-              fi
-            fi
-          fi
-	fi
 
         [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \
             uns="${ws[1][2,-1]}"
 
-        [[ -n "$uns" ]] &&
+	if [[ -n "$uns" ]]; then
+	  uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}"
 	  unset "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]" \
 	        "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]" \
 	        "odopts[${(@)^odopts[(I)${ws[1][1]}[$uns]]}]"
+	fi
 
 	# If we didn't find a matching option description and we were
 	# told to use normal argument descriptions, just increase
@@ -356,7 +314,7 @@ else
 
     # In any case, we have to complete option names here, but we may
     # be in a string that starts with an option names and continues with
-    # the first argument, test that (again, four loops).
+    # the first argument, test that (again, two loops).
 
     opt=yes
     if (( $#dopts )); then
@@ -364,11 +322,12 @@ else
       # Get the option names.
 
       tmp=( "${(@k)dopts}" )
+      prefix="$PREFIX"
       while (( $#tmp )); do
         if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
           def="$dopts[$tmp[1]]"
 	  opt=''
-	  uns="${PREFIX[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
+	  uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
 	  break
         elif compset -P "$tmp[1]"; then
 
@@ -382,29 +341,14 @@ else
 	shift 1 tmp
       done
     fi
-    if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
-      tmp=( "${(@k)dmopts}" )
-      while (( $#tmp )); do
-        if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
-          def="$dmopts[$tmp[1]]"
-	  opt=''
-	  uns="${PREFIX[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
-	  break
-        elif compset -P "$tmp[1]"; then
-	  def="$dmopts[$tmp[1]]"
-	  opt=''
-	  break
-        fi
-	shift 1 tmp
-      done
-    fi
     if [[ -n "$opt" && $#odopts -ne 0 ]]; then
       tmp=( "${(@k)odopts}" )
+      prefix="$PREFIX"
       while (( $#tmp )); do
         if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
           def="$odopts[$tmp[1]]"
 	  opt=''
-	  uns="${PREFIX[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
+	  uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
 	  break
         elif compset -P "$tmp[1]"; then
 	  def="$odopts[$tmp[1]]"
@@ -414,30 +358,16 @@ else
 	shift 1 tmp
       done
     fi
-    if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
-      tmp=( "${(@k)odmopts}" )
-      while (( $#tmp )); do
-        if [[ -n "$sopts" &&  $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
-          def="$odmopts[$tmp[1]]"
-	  opt=''
-	  uns="${PREFIX[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
-	  break
-        elif compset -P "$tmp[1]"; then
-	  def="$odmopts[$tmp[1]]"
-	  opt=''
-	  break
-        fi
-	shift 1 tmp
-      done
-    fi
 
-    [[ -n "$sopts" && -n "$opt" && "$PREFIX" = [-+]* ]] && \
+    [[ -n "$sopts" && -n "$opt" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]] && \
         uns="${PREFIX[2,-1]}"
 
-    [[ -n "$uns" ]] &&
-        unset "opts[${(@)^opts[(I)${pre[1]}[$uns]]}]" \
-	      "dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]" \
-	      "odopts[${(@)^odopts[(I)${pre[1]}[$uns]]}]"
+    if [[ -n "$uns" ]]; then
+      uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}"
+      unset "opts[${(@)^opts[(I)${pre[1]}[$uns]]}]" \
+	    "dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]" \
+	    "odopts[${(@)^odopts[(I)${pre[1]}[$uns]]}]"
+    fi
 
     if [[ -n "$opt" ]]; then
 
@@ -447,12 +377,18 @@ else
       if [[ "$compconfig[option_prefix]" != *(short|all)* ||
             "$PREFIX" = [-+]* ]]; then
         _description expl option
-	if [[ -n "$sopts" && -n "$PREFIX" && -n "$soptseq" && "$PREFIX" = [-+]${~soptseq1} ]]; then
-	  compadd "$expl[@]" -Q - "$PREFIX" && ret=0
+	if [[ -n "$sopts" && -n "$PREFIX" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then
+	  if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then
+	    compadd "$expl[@]" -Q - "${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 next word.
+	    compadd "$expl[@]" -Q - "${PREFIX}" && ret=0
+	  fi
 	else
-          compadd "$expl[@]" -Q - "${(@k)opts}" "${(@k)mopts}" \
-				  "${(@k)odopts}" "${(@k)odmopts}" && ret=0
-	  compadd "$expl[@]" -QS '' - "${(@k)dopts}" "${(@k)dmopts}" && ret=0
+          compadd "$expl[@]" -Q - "${(@k)opts}" "${(@k)odopts}" && ret=0
+	  compadd "$expl[@]" -QS '' - "${(@k)dopts}" && ret=0
         fi
       fi
       [[ $#long -ne 0 &&
@@ -503,5 +439,5 @@ else
 
   # Set the return value.
 
-  [[  nm -ne "$compstate[nmatches]" ]]
+  [[ nm -ne "$compstate[nmatches]" ]]
 fi