about summary refs log tree commit diff
path: root/Completion/Base
diff options
context:
space:
mode:
authorPaul Ackersviller <packersv@users.sourceforge.net>2007-11-04 20:21:53 +0000
committerPaul Ackersviller <packersv@users.sourceforge.net>2007-11-04 20:21:53 +0000
commit4c3c7456c2bb1f008d1e96fc97be320dbd2d8875 (patch)
tree6163cbf77dd9b5f7a3090243d2af57a12402ce5d /Completion/Base
parentefcd73c208db7a327220b3da8eb7eee853c81385 (diff)
downloadzsh-4c3c7456c2bb1f008d1e96fc97be320dbd2d8875.tar.gz
zsh-4c3c7456c2bb1f008d1e96fc97be320dbd2d8875.tar.xz
zsh-4c3c7456c2bb1f008d1e96fc97be320dbd2d8875.zip
Merge of 22858, 22859, and 23182 (up to trunk revision 1.20).
Diffstat (limited to 'Completion/Base')
-rw-r--r--Completion/Base/Utility/_arguments179
1 files changed, 136 insertions, 43 deletions
diff --git a/Completion/Base/Utility/_arguments b/Completion/Base/Utility/_arguments
index a87486168..d1aafd79a 100644
--- a/Completion/Base/Utility/_arguments
+++ b/Completion/Base/Utility/_arguments
@@ -3,9 +3,10 @@
 # Complete the arguments of the current command according to the
 # descriptions given as arguments to this function.
 
-local long cmd="$words[1]" descr mesg subopts opt usecc autod
+local long cmd="$words[1]" descr odescr mesg subopts opt opt2 usecc autod
 local oldcontext="$curcontext" hasopts rawret optarg singopt alwopt
 local setnormarg
+local -a match mbegin mend
 
 long=$argv[(I)--]
 if (( long )); then
@@ -50,9 +51,9 @@ if (( long )); then
 	tmp=( "${(@P)tmp}" )
       fi
       if [[ "$1" = -i* ]]; then
-        iopts=( "$iopts[@]" "$tmp[@]" )
+        iopts+=( "$tmp[@]" )
       else
-        sopts=( "$sopts[@]" "$tmp[@]" )
+        sopts+=( "$tmp[@]" )
       fi
       shift cur
     done
@@ -68,33 +69,89 @@ if (( long )); then
     # those hyphens and anything from the space or tab after the
     # option up to the end.
 
-    lopts=("--${(@)${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$(_call_program options ${~words[1]} --help 2>&1)//\[--/
---}:#[ 	]#-*}//,/
-}}:#[ 	]#--*}#*--}%%[]	 ]*}:#}//\[=/=}")
+   tmp=()
+   _call_program 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.
+	 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.
+       if [[ -z ${tmp[(r)${match[1]%%[^a-zA-Z0-9-]#}]} ]]; then
+	 tmp+=($match[1])
+       fi
+       opt=$match[2]
+     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=()
-    for opt in "${(@)${(@)lopts:#--}%%\=*}"; do
+    # 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=( "$tmp[@]" "$lopts[(r)$opt(|=*)]" )
+          tmp+=( "$lopts[(r)$opt(|[\[:=]*)]" )
     done
     lopts=( "$tmp[@]" )
 
     # Now remove all ignored options ...
 
     while (( $#iopts )); do
-      lopts=( ${lopts:#$~iopts[1]} )
+      lopts=( ${lopts:#$~iopts[1](|[\[:=]*)} )
       shift iopts
     done
 
     # ... and add "same" options
 
     while (( $#sopts )); do
-      lopts=( $lopts ${lopts/$~sopts[1]/$sopts[2]} )
+      # 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
 
@@ -102,17 +159,27 @@ if (( long )); then
     # The last one matches all options; the `special' description and action
     # makes those options be completed without an argument description.
 
-    set -- "$@" '*=FILE*:file:_files' \
-           '*=(DIR|PATH)*:directory:_files -/' '*=*:=: ' '*: :  '
+    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
@@ -124,8 +191,10 @@ if (( long )); then
       # list we have built. If no option matches the pattern, we
       # continue with the next.
 
-      tmp=("${(@M)lopts:##$~pattern}")
-      lopts=("${(@)lopts:##$~pattern}")
+      # 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
 
@@ -138,48 +207,72 @@ if (( long )); then
       if (( $#tmpo )); then
         tmp=("${(@)tmp:#*\[\=*}")
 
-        if [[ "$descr" = :\=* ]]; then
-          for opt in "$tmpo[@]"; do
-            cache=( "$cache[@]"
-                    "${${opt%%\=*}//[^a-zA-Z0-9-]}=::${(L)${opt%\]}#*\=}: " )
-          done
-        else
-          tmpo=("${(@)${(@)tmpo%%\=*}//[^a-zA-Z0-9-]}")
-          if [[ "$descr" = ::* ]]; then
-	    cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
-          else
-	    cache=( "$cache[@]" "${(@)^tmpo}=${dir}:${descr}" )
-          fi
-        fi
+	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:#*\=*}")
 
-        if [[ "$descr" = :\=* ]]; then
-          for opt in "$tmpo[@]"; do
-            cache=( "$cache[@]"
-                    "${${opt%%\=*}//[^a-zA-Z0-9-]}=:${(L)${opt%\]}#*\=}: " )
-          done
-        else
-          tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
-
-	  cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
-        fi
+	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=("${(@)tmp//[^a-zA-Z0-9-]}")
+        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=( "$cache[@]" "${(@)^tmp}${descr}" )
+	  cache+=( "${(@)^tmp}${descr}" )
         else
-	  cache=( "$cache[@]" "$tmp[@]" )
+	  cache+=( "$tmp[@]" )
         fi
       fi
     done
@@ -273,11 +366,11 @@ if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then
 	      action="${${action[3,-1]##[ 	]#}%%[ 	]#}"
 	      if (( ! $state[(I)$action] )); then
                 comparguments -W line opt_args
-                state=( "$state[@]" "$action" )
+                state+=( "$action" )
 	        if [[ -n "$usecc" ]]; then
 	          curcontext="${oldcontext%:*}:$subc"
 	        else
-	          context=( "$context[@]" "$subc" )
+	          context+=( "$subc" )
 	        fi
                 compstate[restore]=''
                 aret=yes
@@ -404,7 +497,7 @@ if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then
           fi
           single=yes
         else
-          next=( "$next[@]" "$odirect[@]" )
+          next+=( "$odirect[@]" )
           _describe -O option \
                     next -Q -M "$matcher" -- \
                     direct -QS '' -M "$matcher" -- \