From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10910 invoked from network); 23 Aug 1999 13:49:25 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 23 Aug 1999 13:49:25 -0000 Received: (qmail 3452 invoked by alias); 23 Aug 1999 13:49:15 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 7467 Received: (qmail 3349 invoked from network); 23 Aug 1999 13:48:05 -0000 Date: Mon, 23 Aug 1999 15:46:54 +0200 (MET DST) Message-Id: <199908231346.PAA03326@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: Tanaka Akira's message of 21 Aug 1999 08:22:55 +0900 Subject: Re: PATCH: completion Tanaka Akira wrote: > Some options take arguments up to end of command line. > > If _arguments supports this style of options, it is also useful for > _cvs, I suppose. Because first non-option argument for cvs command > behaves like that. This tries to implement this. The syntax is: '-opt:*:descr:action' Of course there may be other argument descriptions before the `:*:'. This can also handle multiple arguments ended by a word matching a pattern: '-opt:*pattern:descr:action'. And one can select if the `words' and `CURRENT' parameters should be restricted to those words that are the arguments to the option or to those words covered by the `:*:' description only. This is done by using two or three colons as in: '-opt:*::descr:action' # all args to the option '-opt:first arg:...:*:::descr:action' # only the words covered by `:*:...' Once this fully works, `_arguments' will be incredibly powerful... ;-) There are also fixes for some typos in there... Bye Sven P.S.: I /think/ it should be possible to implement `_find' using `_arguments' now... diff -u od/Zsh/compsys.yo Doc/Zsh/compsys.yo --- od/Zsh/compsys.yo Mon Aug 23 11:42:16 1999 +++ Doc/Zsh/compsys.yo Mon Aug 23 15:37:18 1999 @@ -836,11 +836,13 @@ to automatically find out what should be completed as the argument. The possible completions for option-arguments can be described with the arguments to this function. Each argument contains one description -of the form ::. The message will be printed +of the form `tt(::)'. The message will be printed above the possible completion if the `description_format' configuration key is set (see above). The actions specify what should be done to complete arguments of those options that match -the pattern. The action may be a list of words in brackets or in +the pattern. In both the message and the action a colon can be +included by preceding it with a backslash. The action may be a list of +words in brackets or in parentheses, separated by spaces. A list in brackets denotes possible values for an optional argument, a list in parentheses gives words to complete for mandatory arguments. If the action does @@ -910,6 +912,18 @@ `tt(:)var(message)tt(:)var(action)' or `tt(::)var(message)tt(:)var(action)', where the second form describes an optional argument and the first one describes a mandatory argument. +The last description may also be of the form +`tt(:*:)var(message)tt(:)var(action)' or +`tt(:*)var(pattern)tt(:)var(message)tt(:)var(action)'. These describe +multiple arguments. In the first form all following words on the line +are to be completed as described by the var(action), in the second +form all words up to a word matching the given var(pattern) are to be +completed using the var(action). The `tt(*)' or the var(pattern) may +also be separated from the var(message) by two or three colons. With +two colons the tt(words) special array and the tt(CURRENT) special +parameter are modified to refer only to the words after the option +(with two colons) or to the words covered by this description (with +three colons) during the execution or evaluation of the var(action). In the simplest form the var(opt-spec) is just the option name beginning with a minus or a plus sign, such as `tt(-foo)'. In this @@ -941,8 +955,11 @@ in the description will be shown above the matches. During the evaluation or execution of the action the array `tt(line)' will be set to the command name and normal arguments from the command line, -i.e. to the words from the command line xcluding all options and their +i.e. to the words from the command line excluding all options and their arguments. + +To include a colon in the var(message) or the var(action), it has to +be preceded by a backslash. Normally the option names are taken as multi-character names and a word from the line is considered to contain only one option (or diff -u -r oc/Base/_arguments Completion/Base/_arguments --- oc/Base/_arguments Mon Aug 23 11:42:44 1999 +++ Completion/Base/_arguments Mon Aug 23 15:39:03 1999 @@ -7,6 +7,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ shift 1 ws (( cur-- )) + (( beg++ )) done # Now generate the matches. @@ -313,10 +338,16 @@ 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 @@ if [[ -n "$def" ]]; then - # Ignore the leading colon describing optional arguments. + # Ignore the leading colon or `*...' describing optional arguments. + + 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 - [[ "$def" = :* ]] && def="$def[2,-1]" + 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 @@ # 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 -u -r oc/Base/_long_options Completion/Base/_long_options --- oc/Base/_long_options Mon Aug 23 11:42:44 1999 +++ Completion/Base/_long_options Mon Aug 23 12:01:58 1999 @@ -141,9 +141,9 @@ # 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 @@ _description expl "$descr" - if [[ "$action[1]" = (\[*\]|\(*\)) ]]; then + if [[ "$action" = (\[*\]|\(*\)) ]]; then compadd "$expl[@]" - ${=action[2,-2]} elif [[ "$action" = \{*\} ]]; then eval "$action[2,-2]" -- Sven Wischnowsky wischnow@informatik.hu-berlin.de