about summary refs log tree commit diff
path: root/Completion/Base/_arguments
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Base/_arguments')
-rw-r--r--Completion/Base/_arguments289
1 files changed, 150 insertions, 139 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 120c50934..86cd1c498 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -6,7 +6,7 @@
 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 prefix
+local single uns ret=1 soptseq soptseq1 sopts prefix line
 
 # Associative arrays used to collect information about the options.
 
@@ -117,182 +117,185 @@ else
   sopts=''
 fi
 
-if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
-
-   # If the current words starts with `--' and we should use long
-   # options, just call...
+# Parse the command line...
 
-  _long_options "$long[@]"
-else
+ws=( "${(@)words[2,-1]}" )
+cur=$(( CURRENT-2 ))
+nth=1
+liine=( "$words[1]" )
 
-  # Otherwise parse the command line...
+# ...until the current word is reached.
 
-  ws=( "${(@)words[2,-1]}" )
-  cur=$(( CURRENT-2 ))
-  nth=1
+while [[ cur -gt 0 ]]; do
 
-  # ...until the current word is reached.
+  # `def' holds the description for the option we are currently after.
+  # Check if the next argument for the option is optional.
 
-  while [[ cur -gt 0 ]]; do
+  if [[ "$def" = :* ]]; then
+    opt=yes
+  else
+    opt=''
+  fi
+  arg=''
 
-    # `def' holds the description for the option we are currently after.
-    # Check if the next argument for the option is optional.
+  # Remove one description/action pair from `def' if that isn't empty.
 
-    if [[ "$def" = :* ]]; then
-      opt=yes
+  if [[ -n "$def" ]]; then
+    if [[ "$def" = ?*:*:* ]]; then
+      def="${def#?*:*:}"
     else
-      opt=''
+      def=''
     fi
-    arg=''
+  else
 
-    # Remove one description/action pair from `def' if that isn't empty.
+    # If it is empty, and the word starts with `--' and we should
+    # complete long options, just ignore this word, otherwise make sure
+    # we test for options below and handle normal arguments.
 
-    if [[ -n "$def" ]]; then
-      if [[ "$def" = ?*:*:* ]]; then
-        def="${def#?*:*:}"
-      else
-        def=''
-      fi
+    if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
+      opt=yes
+      arg=yes
     else
+      def=''
+    fi
+  fi
 
-      # If it is empty, and the word starts with `--' and we should
-      # complete long options, just ignore this word, otherwise make sure
-      # we test for options below and handle normal arguments.
+  if [[ -n "$opt" ]]; then
 
-      if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
-        opt=yes
-	arg=yes
-      else
-        def=''
-      fi
-    fi
+    # `opt' was set above if we have to test if the word is an option.
+    # We first test for the simple options -- those without arguments or
+    # those whose arguments have to be given as separate words.
 
-    if [[ -n "$opt" ]]; then
+    if (( $+opts[$ws[1]] )); then
 
-      # `opt' was set above if we have to test if the word is an option.
-      # We first test for the simple options -- those without arguments or
-      # those whose arguments have to be given as separate words.
+      # Options that may only be given once are removed from the
+      # associative array so that we don't offer them again.
 
-      if (( $+opts[$ws[1]] )); then
+      def="$opts[$ws[1]]"
+      [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]"
+    else
+      uns=''
+      if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then
+	tmp="${ws[1][1]}${ws[1][-1]}"
+	if (( $+opts[$tmp] )); then
+	  def="$opts[$tmp]"
+	  uns="${ws[1][2,-1]}"
+	  opt=''
+	fi
+      fi
 
-        # Options that may only be given once are removed from the
-        # associative array so that we don't offer them again.
+      # 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 two loops looking very much alike.
 
-        def="$opts[$ws[1]]"
-        [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]"
-      else
-        uns=''
-        if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then
-	  tmp="${ws[1][1]}${ws[1][-1]}"
-	  if (( $+opts[$tmp] )); then
-	    def="$opts[$tmp]"
-	    uns="${ws[1][2,-1]}"
-	    opt=''
-	  fi
-        fi
+      if [[ -n "$opt" && $#dopts -ne 0 ]]; then
 
-        # 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 two loops looking very much alike.
+	# First we get the option names.
 
-        if [[ -n "$opt" && $#dopts -ne 0 ]]; then
+	tmp=( "${(@k)dopts}" )
 
-	  # First we get the option names.
+	# Then we loop over them and see if the current word begins
+	# with one of the option names.
 
-	  tmp=( "${(@k)dopts}" )
+	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
 
-	  # Then we loop over them and see if the current word begins
-	  # with one of the option names.
+	if (( $#tmp )); then
 
-	  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
+	  # It does. So use the description for it, but only from
+	  # the second argument on, because we are searching the
+	  # description for the next command line argument.
+
+	  opt=''
+	  def="$dopts[$tmp[1]]"
+	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$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
+          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
-	    shift 1 tmp
-	  done
+	  elif [[ "$ws[1]" = ${tmp[1]}* ]]; then
+	    break
+	  fi
+	  shift 1 tmp
+	done
 
-	  if (( $#tmp )); then
+	if (( $#tmp )); then
+	  opt=''
+	  def="$odopts[$tmp[1]]"
+	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]"
 
-	    # It does. So use the description for it, but only from
-	    # the second argument on, because we are searching the
-	    # description for the next command line argument.
+	  # 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.
 
-	    opt=''
-	    def="$dopts[$tmp[1]]"
-	    [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]"
+	  if [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) ||
+                ( -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
               def=''
-	    fi
-          fi
-        fi
-        if [[ -n "$opt" && $#odopts -ne 0 ]]; then
-	  tmp=( "${(@k)odopts}" )
-	  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="$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]}" ) ||
-		  		     ( $tmp[1] != [-+]? && "$ws[1]" != "$tmp[1]" ) ) ) ]]; then
-	      if [[ "$def" = ?*:*:* ]]; then
-                def="${def#?*:*:}"
-              else
-                def=''
-              fi
-	    fi
-          fi
+            fi
+	  fi
         fi
+      fi
 
-        [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \
-            uns="${ws[1][2,-1]}"
+      [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \
+          uns="${ws[1][2,-1]}"
 
-	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 [[ -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
-	# our counter `nth'.
+      # If we didn't find a matching option description and we were
+      # told to use normal argument descriptions, just increase
+      # our counter `nth'.
 
-        if [[ -n "$opt" && -n "$arg" ]]; then
-          def=''
-	  (( nth++ ))
-        fi
+      if [[ -n "$opt" && -n "$arg" ]]; then
+        def=''
+	line=( "$line[@]" "$ws[1]" )
+	(( nth++ ))
       fi
     fi
+  fi
 
-    shift 1 ws
-    (( cur-- ))
-  done
+  shift 1 ws
+  (( cur-- ))
+done
+
+# Now generate the matches.
+
+if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
 
-  # Now generate the matches.
+  # If the current words starts with `--' and we should use long
+  # options, just call...
+
+  _long_options "$long[@]"
+
+else
 
   nm="$compstate[nmatches]"
 
@@ -379,9 +382,11 @@ else
         _description expl option
 	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
+	    compadd "$expl[@]" -Q \
+                    -y "( ${(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 next word.
 	    compadd "$expl[@]" -Q - "${PREFIX}" && ret=0
@@ -418,11 +423,17 @@ else
       # An empty action means that we should just display a message.
       _message "$descr"
       return ret
-    elif [[ "$action[1]" = \( ]]; then
+    elif [[ "$action[1]" = \(*\) ]]; then
 
       # Anything inside `(...)' is added directly.
 
       compadd "$expl[@]" - ${=action[2,-2]}
+    elif [[ "$action" = \{*\} ]]; then
+
+      # A string in braces is evaluated.
+
+      eval "$action[2,-2]"
+
     elif [[ "$action" = \ * ]]; then
 
       # If the action starts with a space, we just call it.