about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/_arguments88
-rw-r--r--Completion/Base/_long_options8
2 files changed, 77 insertions, 19 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 86cd1c498..d51e6d0af 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -7,6 +7,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 line
+local beg optbeg argbeg
 
 # Associative arrays used to collect information about the options.
 
@@ -122,7 +123,10 @@ fi
 ws=( "${(@)words[2,-1]}" )
 cur=$(( CURRENT-2 ))
 nth=1
-liine=( "$words[1]" )
+line=( "$words[1]" )
+beg=2
+argbeg=2
+optbeg=2
 
 # ...until the current word is reached.
 
@@ -138,15 +142,27 @@ while [[ cur -gt 0 ]]; do
   fi
   arg=''
 
+  # See if we are after an option getting n arguments ended by something
+  # that matches the current word.
+
+  if [[ "$def" = \**[^\\]:* && "$ws[1]" = ${~${(M)def#*[^\\]:}[2,-2]} ]]; then
+    def=''
+    shift 1 ws
+    (( cur-- ))
+    (( beg++ ))
+    continue
+  fi
+
   # Remove one description/action pair from `def' if that isn't empty.
 
-  if [[ -n "$def" ]]; then
-    if [[ "$def" = ?*:*:* ]]; then
-      def="${def#?*:*:}"
+  if [[ -n "$def" && "$def" != \** ]]; then
+    if [[ "$def" = ?*[^\\]:*[^\\]:* ]]; then
+      def="${def#?*[^\\]:*[^\\]:}"
+      argbeg="$beg"
     else
       def=''
     fi
-  else
+  elif [[ -z "$def" ]]; then
 
     # If it is empty, and the word starts with `--' and we should
     # complete long options, just ignore this word, otherwise make sure
@@ -179,6 +195,8 @@ while [[ cur -gt 0 ]]; do
 	tmp="${ws[1][1]}${ws[1][-1]}"
 	if (( $+opts[$tmp] )); then
 	  def="$opts[$tmp]"
+	  optbeg="$beg"
+	  argbeg="$beg"
 	  uns="${ws[1][2,-1]}"
 	  opt=''
 	fi
@@ -217,9 +235,11 @@ while [[ cur -gt 0 ]]; do
 
 	  opt=''
 	  def="$dopts[$tmp[1]]"
+	  optbeg="$beg"
+	  argbeg="$beg"
 	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]"
-	  if [[ "$def" = ?*:*:* ]]; then
-            def="${def#?*:*:}"
+	  if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then
+            def="${def#?*[^\\]:*[^\\]:}"
           else
             def=''
 	  fi
@@ -242,6 +262,8 @@ while [[ cur -gt 0 ]]; do
 	if (( $#tmp )); then
 	  opt=''
 	  def="$odopts[$tmp[1]]"
+	  optbeg="$beg"
+	  argbeg="$beg"
 	  [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]"
 
 	  # For options whose first argument *may* come after the
@@ -251,8 +273,10 @@ while [[ cur -gt 0 ]]; do
 	  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#?*:*:}"
+	    if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then
+              def="${def#?*[^\\]:*[^\\]:}"
+	      optbeg="$beg"
+	      argbeg="$beg"
             else
               def=''
             fi
@@ -284,6 +308,7 @@ while [[ cur -gt 0 ]]; do
 
   shift 1 ws
   (( cur-- ))
+  (( beg++ ))
 done
 
 # Now generate the matches.
@@ -313,10 +338,16 @@ else
 
       def="$args[nth]"
       [[ -z "$def" ]] && def="$rest"
+
+      if [[ "$def" = \** ]]; then
+        def="${def#*[^\\]:}"
+	[[ "$def" = :* ]] && def="$def[2,-1]"
+	[[ "$def" = :* ]] && def="$def[2,-1]"
+      fi
     fi
 
     # 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
+    # be in a string that starts with an option name and continues with
     # the first argument, test that (again, two loops).
 
     opt=yes
@@ -407,14 +438,41 @@ else
 
   if [[ -n "$def" ]]; then
 
-    # Ignore the leading colon describing optional arguments.
+    # Ignore the leading colon or `*...' describing optional arguments.
 
-    [[ "$def" = :* ]] && def="$def[2,-1]"
+    if [[ "$def" = :* ]]; then
+      def="$def[2,-1]"
+    elif [[ "$def" = \** ]]; then
+      tmp="${${(M)def#*[^\\]:}[2,-2]}"
+      def="${def#*[^\\]:}"
+
+      if [[ "$def" = :* ]]; then
+        if [[ "$def" = ::* ]]; then
+          def="$def[3,-1]"
+	  beg=$argbeg
+	else
+	  def="$def[2,-1]"
+	  beg=$optbeg
+	fi
+
+	shift beg words
+	(( CURRENT -= beg ))
+
+	if [[ -n "$tmp" ]]; then
+          tmp="$words[(ib:CURRENT:)${~tmp}]"
+	  [[ tmp -le $#words ]] && words=( "${(@)words[1,tmp-1]}" )
+	fi
+      fi
+    fi
 
     # Get the description and the action.
 
-    descr="${def%%:*}"
-    action="${${def#*:}%%:*}"
+    descr="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}"
+    if [[ "$def" = *[^\\]:*[^\\]:* ]]; then
+      action="${${${(M)${def#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}"
+    else
+      action="${${def#*[^\\]:}//\\\\:/:}"
+    fi
 
     _description expl "$descr"
 
@@ -423,7 +481,7 @@ else
       # An empty action means that we should just display a message.
       _message "$descr"
       return ret
-    elif [[ "$action[1]" = \(*\) ]]; then
+    elif [[ "$action" = \(*\) ]]; then
 
       # Anything inside `(...)' is added directly.
 
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
index 716ff8884..f0aa2eaff 100644
--- a/Completion/Base/_long_options
+++ b/Completion/Base/_long_options
@@ -141,9 +141,9 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
     # First, we get the pattern and the action to use and take them
     # from the positional parameters.
 
-    pattern="${1%%:*}"
-    descr="${${1#*:}%%:*}"
-    action="${1#*:*:}"
+    pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
+    descr="${${${(M)${1#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}"
+    action="${${1#*[^\\]:*[^\\]:}//\\\\:/:}"
     shift
 
     # We get all options matching the pattern and take them from the
@@ -257,7 +257,7 @@ if [[ "$str" = *\=* ]]; then
 
       _description expl "$descr"
 
-      if [[ "$action[1]" = (\[*\]|\(*\)) ]]; then
+      if [[ "$action" = (\[*\]|\(*\)) ]]; then
         compadd "$expl[@]" - ${=action[2,-2]}
       elif [[ "$action" = \{*\} ]]; then
         eval "$action[2,-2]"