Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: completion
- X-seq: zsh-workers 7463
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: Re: PATCH: completion
- Date: Mon, 23 Aug 1999 11:32:16 +0200 (MET DST)
- In-reply-to: Tanaka Akira's message of 21 Aug 1999 08:22:55 +0900
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Tanaka Akira wrote:
> 1. The help message may not suited for _long_options.
>
> For example, help message of "patch" contains:
> -p NUM --strip=NUM Strip NUM leading components from file names.
>
> The options are not separeted by ",".
I found the same problem with the output of `gprof' over the weekend
and the patch below fixes that problem.
> I avoid this problem by modifying the help message.
> # http://www.ldl.jaist.ac.jp/~akr/junk/patch-2.5.3-cvsaware-19990820.patch
>
> But, in general, help messages may not able to modify. Therefore I
> think it is useful that _arguments can handle options started with
> "--".
>
> # Also, if _arguments supports options started with "--" directly,
> # opt-spec to specify both "--xxx=yyy" and "--xxx yyy" at once may
> # useful.
I don't agree here -- do you know of any command that accepts a `--'
option which gets its argument in the next word? If so, I think that
command shouldn't do that.
> 2. I would like to refer the parsed arguments in completers.
>
> I think this is useful in many cases.
> For example, if the completer for port of telnet can refer host
> argument, it can complete ports precisely: "nntp" for news servers,
> "smtp" for mail servers, etc. If the completer for emacs can check
> whether the argument of -f is batch-byte-compile, we can complete only
> *.el.
(I think you mean completion functions, the term `completer' refers to
those top-level thingies like `_complete'.)
Yes, another one of the things I hacked at the weekend. The patch
makes the non-options from the line available in the `line' array
(there may be a better name) in everything that gets called or
evaluated from `_arguments' (or `_long_options' if that was called
from `_arguments').
> 3. "xterm -e" style.
>
> 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.
Yes, again, I thought about this when I wrote `_arguments' but
couldn't think of a syntax and then simply forgot to write it. I think
I'll send a patch for this some time...
> Also, I found the problem about associative array with rcexpandparam.
>
> Z(2):akr@is27e1u11% zsh -f
> is27e1u11% typeset -A arr
> is27e1u11% arr[a]=
> is27e1u11% print -lr - "A${(@)^arr[(I)b]}B"
> AB
>
> This should be empty. Because of this problem, completions for
> single-letter option doesn't work well.
No, it shouldn't -- there is one string resulting from the expansion,
even it is the empty string.
What exactly doesn't work with single-letter option because of this?
(I'm a bit too lazy to search ;-) I guess that this can be avoided by
adding a ${...:#} somewhere.
Other things the patch contains:
- a fixlet for `compadd' it didn't skip over arguments of the second
to nth occurrence of an option that was given more than once
- first attempt for auto-param-slash
- it changes the `Commands/*' files to not contain the `-n' option --
this is made implicit in `compinit' in the same way this is implicit
for normal `compdef's
- actions in `_arguments' and `_long_options' can be made evaluated
with the new syntax `{string}'
- `_arguments' lists short options in a better readable form
- it cleans up some functions to make use of helper functions like
`_hosts' and `_users'
- the file `Util/completion-style-guide' contains the beginnings of a
style guide for completion functions; for now this is just a simple
list of things to do or not to do
Bye
Sven
diff -u os/Zle/compctl.c Src/Zle/compctl.c
--- os/Zle/compctl.c Fri Aug 20 15:18:19 1999
+++ Src/Zle/compctl.c Mon Aug 23 10:23:09 1999
@@ -1850,8 +1850,9 @@
*sp = p + 1;
p = "" - 1;
} else if (argv[1]) {
+ argv++;
if (!*sp)
- *sp = *++argv;
+ *sp = *argv;
p = "" - 1;
} else {
zerrnam(name, e, NULL, *p);
diff -u od/Zsh/compsys.yo Doc/Zsh/compsys.yo
--- od/Zsh/compsys.yo Fri Aug 20 15:18:10 1999
+++ Doc/Zsh/compsys.yo Mon Aug 23 10:23:09 1999
@@ -846,7 +846,7 @@
gives words to complete for mandatory arguments. If the action does
not start with a bracket or parentheses, it should be the name of a
command (probably with arguments) that should be invoked to complete
-after the equal sign. E.g.:
+after the equal sign or a string in braces that will be evaluated. E.g.:
example(_long_options '*\*' '(yes no)' \
'*=FILE*' '_files' \
@@ -930,14 +930,19 @@
In each of the cases above, the var(action) says how the possible
completions should be generated. In cases where only one of a fixed
set of strings can be completed, these string can directly be given as
-a list in parentheses, as in `tt(:foo:(foo bar baz))'. If the
-var(action) does not begin with an opening parentheses, it will be
-split into separate words and executed. If the var(action) starts with
-a space, this list of words will be invoked unchanged, otherwise it
-will be invoked with some extra string placed after the first word
-which can be given as arguments to the tt(compadd) and tt(compgen)
-builtins and which make sure that the var(message) given in the
-description will be shown above the matches.
+a list in parentheses, as in `tt(:foo:(foo bar baz))'. A string in
+braces will be evaluated to generate the matches and if the
+var(action) does not begin with an opening parentheses or brace, it
+will be split into separate words and executed. If the var(action)
+starts with a space, this list of words will be invoked unchanged,
+otherwise it will be invoked with some extra string placed after the
+first word which can be given as arguments to the tt(compadd) and
+tt(compgen) builtins and which make sure that the var(message) given
+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
+arguments.
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 10:12:47 1999
+++ Completion/Base/_arguments Mon Aug 23 10:38:49 1999
@@ -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 @@
sopts=''
fi
-if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
+# Parse the command line...
- # If the current words starts with `--' and we should use long
- # options, just call...
+ws=( "${(@)words[2,-1]}" )
+cur=$(( CURRENT-2 ))
+nth=1
+liine=( "$words[1]" )
- _long_options "$long[@]"
-else
+# ...until the current word is reached.
- # Otherwise parse the command line...
+while [[ cur -gt 0 ]]; do
- ws=( "${(@)words[2,-1]}" )
- cur=$(( CURRENT-2 ))
- nth=1
+ # `def' holds the description for the option we are currently after.
+ # Check if the next argument for the option is optional.
+
+ if [[ "$def" = :* ]]; then
+ opt=yes
+ else
+ opt=''
+ fi
+ arg=''
- # ...until the current word is reached.
+ # Remove one description/action pair from `def' if that isn't empty.
- while [[ cur -gt 0 ]]; do
+ if [[ -n "$def" ]]; then
+ if [[ "$def" = ?*:*:* ]]; then
+ def="${def#?*:*:}"
+ else
+ def=''
+ fi
+ else
- # `def' holds the description for the option we are currently after.
- # Check if the next argument for the option is optional.
+ # 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 [[ "$def" = :* ]]; then
+ if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
opt=yes
+ arg=yes
else
- opt=''
+ def=''
fi
- arg=''
+ fi
- # Remove one description/action pair from `def' if that isn't empty.
+ if [[ -n "$opt" ]]; then
- if [[ -n "$def" ]]; then
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- else
+ # `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 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 [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
- opt=yes
- arg=yes
- else
- def=''
+ if (( $+opts[$ws[1]] )); then
+
+ # Options that may only be given once are removed from the
+ # associative array so that we don't offer them again.
+
+ 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
- fi
- if [[ -n "$opt" ]]; 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.
- # `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" && $#dopts -ne 0 ]]; then
- if (( $+opts[$ws[1]] )); then
+ # First we get the option names.
- # Options that may only be given once are removed from the
- # associative array so that we don't offer them again.
+ tmp=( "${(@k)dopts}" )
- 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=''
+ # Then we loop over them and see if the current word begins
+ # with one of the option names.
+
+ 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
- fi
+ shift 1 tmp
+ done
+
+ if (( $#tmp )); 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.
-
- if [[ -n "$opt" && $#dopts -ne 0 ]]; then
-
- # First we get the option names.
-
- tmp=( "${(@k)dopts}" )
-
- # Then we loop over them and see if the current word begins
- # with one of the option names.
-
- 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.
-
- opt=''
- def="$dopts[$tmp[1]]"
- [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$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
- 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
+ fi
- 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
+ [[ -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 @@
_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 @@
# 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.
diff -u -r oc/Base/_brace_parameter Completion/Base/_brace_parameter
--- oc/Base/_brace_parameter Mon Aug 23 10:12:47 1999
+++ Completion/Base/_brace_parameter Mon Aug 23 10:23:10 1999
@@ -2,16 +2,17 @@
setopt localoptions extendedglob
-local lp ls n q suf=''
+local lp ls n q
if [[ "$SUFFIX" = *\}* ]]; then
ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
SUFFIX="${SUFFIX%%\}*}"
+ suf=()
elif [[ "$LBUFFER" = *\$\{[^}]#\$\{[^}]#$PREFIX ||
"$compstate[insert]" = *menu* ]]; then
- suf='}'
+ suf=(-b '')
else
- suf='} '
+ suf=(-b ' ')
fi
lp="$LBUFFER[1,-${#PREFIX}-1]"
@@ -21,4 +22,4 @@
[[ n -gt 0 ]] && suf=''
-_parameters -Qs "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/}'
+_parameters "$suf[@]" -Qs "${q[1,-n-1]}" -r '-:?#%+=[/}'
diff -u -r oc/Base/_condition Completion/Base/_condition
--- oc/Base/_condition Mon Aug 23 10:12:47 1999
+++ Completion/Base/_condition Mon Aug 23 10:23:10 1999
@@ -7,11 +7,10 @@
elif [[ "$prev" = -([no]t|ef) ]]; then
_files
else
- local ret=1 expl
+ local ret=1
_files && ret=0
- _description expl parameter
- compgen "$expl[@]" -v && ret=0
+ _parameters && ret=0
return ret
fi
diff -u -r oc/Base/_long_options Completion/Base/_long_options
--- oc/Base/_long_options Mon Aug 23 10:12:47 1999
+++ Completion/Base/_long_options Mon Aug 23 10:44:58 1999
@@ -112,8 +112,9 @@
# those hyphens and anything from the space or comma after the
# option up to the end.
- opts=("--${(@)^${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/
-}}:#[ ]#--*}#*--}%%[, ]*}")
+ opts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help 2>&1)//\[--/
+--}:#[ ]#-*}//,/
+}}:#[ ]#--*}#*--}%%[, ]*}:#}")
# Now remove all ignored options ...
@@ -256,15 +257,15 @@
_description expl "$descr"
- if [[ "$action[1]" = (\[|\() ]]; then
+ if [[ "$action[1]" = (\[*\]|\(*\)) ]]; then
compadd "$expl[@]" - ${=action[2,-2]}
- elif (( $#action )); then
- if [[ "$action" = \ * ]]; then
- ${(e)=~action}
- else
- action=($=action)
- ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
- fi
+ elif [[ "$action" = \{*\} ]]; then
+ eval "$action[2,-2]"
+ elif [[ "$action" = \ * ]]; then
+ ${(e)=~action}
+ elif [[ -n "$action" ]]; then
+ action=($=action)
+ ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
else
_message "$descr"
fi
@@ -308,15 +309,15 @@
_description expl "$partd"
- if (( $#parta )); then
- if [[ "$parta[1]" = (\[|\() ]]; then
- compadd "$expl[@]" - ${=parta[2,-2]}
- elif [[ "$parta" = \ * ]]; then
- ${(e)=~parta}
- else
- action=($=parta)
- ${(e)~parta[1]} "$expl[@]" ${(e)~action[2,-1]}
- fi
+ if [[ "$parta[1]" = (\[*\]|\(*\)) ]]; then
+ compadd "$expl[@]" - ${=parta[2,-2]}
+ elif [[ "$parta" = \{*\} ]]; then
+ eval "$parta[2,-2]"
+ elif [[ "$parta" = \ * ]]; then
+ ${(e)=~parta}
+ elif [[ -n "$parta" ]]; then
+ action=($=parta)
+ ${(e)~action[1]} "$expl[@]" ${(e)~action[2,-1]}
else
compadd -S '' - "$PREFIX"
fi
@@ -346,8 +347,6 @@
anum=1
for name in "$_lo_cache_names[@]"; do
- action="$_lo_cache_actions[anum]"
-
_description expl option
if [[ "$name" = *_optarg_* ]]; then
diff -u -r oc/Base/_math Completion/Base/_math
--- oc/Base/_math Mon Aug 23 10:12:47 1999
+++ Completion/Base/_math Mon Aug 23 10:23:11 1999
@@ -1,7 +1,5 @@
#compdef -math-
-local expl
-
if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then
IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}"
PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
@@ -11,5 +9,4 @@
SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
fi
-_description expl parameter
-compgen "$expl[@]" -v
+_parameters
diff -u -r oc/Base/_parameter Completion/Base/_parameter
--- oc/Base/_parameter Mon Aug 23 10:12:47 1999
+++ Completion/Base/_parameter Mon Aug 23 10:23:11 1999
@@ -1,7 +1,7 @@
#compdef -parameter-
if [[ "$compstate[insert]" = *menu* ]]; then
- _parameters
+ _parameters -s ''
else
- _parameters -S ' ' -r '['
+ _parameters -s ' '
fi
diff -u -r oc/Base/_tilde Completion/Base/_tilde
--- oc/Base/_tilde Mon Aug 23 10:12:47 1999
+++ Completion/Base/_tilde Mon Aug 23 10:23:11 1999
@@ -41,7 +41,7 @@
if (( $# )); then
d=( "$@" )
else
- _description d user
+ _description d 'user or named directory'
fi
fi
diff -u -r oc/Base/_vars Completion/Base/_vars
--- oc/Base/_vars Mon Aug 23 10:12:47 1999
+++ Completion/Base/_vars Mon Aug 23 10:23:11 1999
@@ -20,6 +20,5 @@
compadd "$expl[@]" $addclose - ${(kP)var}
fi
else
- _description expl parameter
- compgen "$expl[@]" -v
+ _parameter
fi
diff -u -r oc/Builtins/_vars_eq Completion/Builtins/_vars_eq
--- oc/Builtins/_vars_eq Mon Aug 23 10:12:49 1999
+++ Completion/Builtins/_vars_eq Mon Aug 23 10:23:11 1999
@@ -1,6 +1,3 @@
#compdef declare export integer local readonly typeset
-local expl
-
-_description expl parameter
-compgen "$expl[@]" -v -q -S '='
+_parameters -q -S '='
diff -u -r oc/Builtins/_zftp Completion/Builtins/_zftp
--- oc/Builtins/_zftp Mon Aug 23 10:12:49 1999
+++ Completion/Builtins/_zftp Mon Aug 23 10:23:12 1999
@@ -23,47 +23,46 @@
case $subcom in
*(cd|ls|dir))
- # complete remote directories; we could be smarter about hiding prefixes
- zfcd_match $PREFIX $SUFFIX
- _description expl 'remote directory'
- (( $#reply )) && compadd "$expl[@]" -S/ -q - $reply
- ;;
+ # complete remote directories; we could be smarter about hiding prefixes
+ zfcd_match $PREFIX $SUFFIX
+ _description expl 'remote directory'
+ (( $#reply )) && compadd "$expl[@]" -S/ -q - $reply
+ ;;
*(get(|at)|gcp|delete|remote))
- # complete remote files
- zfget_match $PREFIX $SUFFIX
- _description expl 'remote file'
- (( $#reply )) && compadd "$expl[@]" -F fignore - $reply
- ;;
+ # complete remote files
+ zfget_match $PREFIX $SUFFIX
+ _description expl 'remote file'
+ (( $#reply )) && compadd "$expl[@]" -F fignore - $reply
+ ;;
*(put(|at)|pcp))
- # complete local files
- _files
- ;;
+ # complete local files
+ _files
+ ;;
*(open|anon|params))
- # complete hosts: should do cleverer stuff with user names
- _description expl host
- compgen "$expl[@]" -k hosts
- ;;
+ # complete hosts: should do cleverer stuff with user names
+ _hosts
+ ;;
*(goto|mark))
- # complete bookmarks. First decide if ncftp mode is go.
- _description expl bookmark
- if [[ $words[2] = -*n* ]]; then
- if [[ -f ~/.ncftp/bookmarks ]]; then
- compadd "$expl[@]" - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
+ # complete bookmarks. First decide if ncftp mode is go.
+ _description expl bookmark
+ if [[ $words[2] = -*n* ]]; then
+ if [[ -f ~/.ncftp/bookmarks ]]; then
+ compadd "$expl[@]" - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
+ fi
+ else
+ if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
+ compadd "$expl[@]" - $(awk '{print $1}' $ZFTP_BMFILE)
+ fi
fi
- else
- if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
- compadd "$expl[@]" - $(awk '{print $1}' $ZFTP_BMFILE)
- fi
- fi
- ;;
+ ;;
*)
- # dunno... try ordinary completion after all.
- unset _compskip
- return 1
- ;;
+ # dunno... try ordinary completion after all.
+ unset _compskip
+ return 1
+ ;;
esac
diff -u -r oc/Commands/_correct_filename Completion/Commands/_correct_filename
--- oc/Commands/_correct_filename Mon Aug 23 10:12:49 1999
+++ Completion/Commands/_correct_filename Mon Aug 23 10:23:12 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \C-xC
+#compdef -k complete-word \C-xC
# Function to correct a filename. Can be used as a completion widget,
# or as a function in its own right, in which case it will print the
diff -u -r oc/Commands/_correct_word Completion/Commands/_correct_word
--- oc/Commands/_correct_word Mon Aug 23 10:12:49 1999
+++ Completion/Commands/_correct_word Mon Aug 23 10:23:12 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \C-xc
+#compdef -k complete-word \C-xc
# Simple completion front-end implementing spelling correction.
# The maximum number of errors is set quite high, and
diff -u -r oc/Commands/_expand_word Completion/Commands/_expand_word
--- oc/Commands/_expand_word Mon Aug 23 10:12:50 1999
+++ Completion/Commands/_expand_word Mon Aug 23 10:23:12 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \C-xe
+#compdef -k complete-word \C-xe
# Simple completion front-end implementing expansion.
#
diff -u -r oc/Commands/_history_complete_word Completion/Commands/_history_complete_word
--- oc/Commands/_history_complete_word Mon Aug 23 10:12:50 1999
+++ Completion/Commands/_history_complete_word Mon Aug 23 10:23:12 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \e/
+#compdef -k complete-word \e/
local expl
diff -u -r oc/Commands/_most_recent_file Completion/Commands/_most_recent_file
--- oc/Commands/_most_recent_file Mon Aug 23 10:12:50 1999
+++ Completion/Commands/_most_recent_file Mon Aug 23 10:23:12 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \C-xm
+#compdef -k complete-word \C-xm
# Complete the most recent file matching the pattern on the line so
# far: globbing is active, i.e. *.txt will be expanded to the most recent
diff -u -r oc/Commands/_read_comp Completion/Commands/_read_comp
--- oc/Commands/_read_comp Mon Aug 23 10:12:50 1999
+++ Completion/Commands/_read_comp Mon Aug 23 10:23:13 1999
@@ -1,4 +1,4 @@
-#compdef -kn complete-word \C-x\C-r
+#compdef -k complete-word \C-x\C-r
# This allows an on-the-fly choice of completions. On typing the key
# sequence given above, you will be prompted for a string of arguments. If
diff -u -r oc/Core/_parameters Completion/Core/_parameters
--- oc/Core/_parameters Mon Aug 23 10:12:51 1999
+++ Completion/Core/_parameters Mon Aug 23 11:03:48 1999
@@ -1,16 +1,67 @@
#autoload
# This should be used to complete parameter names if you need some of the
-# extra options of compadd. It completes only non-local parameters. All
-# arguments are given to compadd.
+# extra options of compadd. It completes only non-local parameters.
+# If the first argument is `-s' or `-b' auto_param_slash will be tested
+# and slashes will be added to parameters containing a directory. `-s' is
+# for parameter expansions without braces and `-b' is for expansions with
+# braces. A `-' as the first argument is ignored and in all cases all
+# other arguments will be given to `compadd'.
-local expl
+
+setopt localoptions extendedglob
+
+local pars expl slash suf
+
+if [[ "$1" = -s ]]; then
+ slash=normal
+ suf="$2"
+ shift 2
+elif [[ "$1" = -b ]]; then
+ slash=brace
+ suf="$2"
+ shift 2
+elif [[ "$1" = - ]]; then
+ shift
+fi
_description expl parameter
if zmodload -e parameter; then
setopt localoptions extendedglob
- compadd "$expl[@]" "$@" - ${(k)parameters[(R)^*local*]}
+ pars=( ${(k)parameters[(R)^*local*]} )
+else
+ pars=( ${${${(f)"$(typeset +)"}:#*local *}##* } )
+fi
+
+if [[ -n "$slash" && -o autoparamslash ]]; then
+ local i dirs nodirs ret=1
+
+ dirs=()
+ nodirs=()
+ for i in $pars; do
+ if [[ -d "${(P)i}" ]]; then
+ dirs=( $dirs $i )
+ else
+ nodirs=( $nodirs $i )
+ fi
+ done
+
+ if [[ "$slash" = normal ]]; then
+ compadd -S "/${suf%% #}" -r ' [/:' "$expl[@]" "$@" - $dirs && ret=0
+ compadd -S "$suf" -r ' [:' "$expl[@]" "$@" - $nodirs && ret=0
+ elif [[ "$slash" = brace ]]; then
+ compadd -S "}/${suf%% #}" -r '-:?#%+=[/}' "$expl[@]" "$@" - $dirs && ret=0
+ compadd -S "}$suf" -r '-:?#%+=[/}' "$expl[@]" "$@" - $nodirs && ret=0
+ fi
+
+ return ret
else
- compadd "$expl[@]" "$@" - ${${${(f)"$(typeset +)"}:#*local *}##* }
+ if [[ "$slash" = normal ]]; then
+ compadd -S "$suf" -r ' [:' "$expl[@]" "$@" - $pars
+ elif [[ "$slash" = brace ]]; then
+ compadd -S "}$suf" -r '-:?#%+=[/}' "$expl[@]" "$@" - $pars
+ else
+ compadd "$expl[@]" "$@" - $pars
+ fi
fi
diff -u -r oc/Core/compinit Completion/Core/compinit
--- oc/Core/compinit Mon Aug 23 10:12:51 1999
+++ Completion/Core/compinit Mon Aug 23 10:23:13 1999
@@ -379,7 +379,7 @@
case $_i_tag in
(\#compdef)
if [[ $_i_line[1] = -[pPk](n|) ]]; then
- compdef ${_i_line[1]}a "${_i_file:t}" "${(@)_i_line[2,-1]}"
+ compdef ${_i_line[1]}na "${_i_file:t}" "${(@)_i_line[2,-1]}"
else
compdef -na "${_i_file:t}" "${_i_line[@]}"
fi
diff -u -r oc/User/_chown Completion/User/_chown
--- oc/User/_chown Mon Aug 23 10:12:58 1999
+++ Completion/User/_chown Mon Aug 23 10:23:13 1999
@@ -4,14 +4,10 @@
if [[ $words[1] = chgrp ]] || compset -P '*[:.]'; then
_groups
else
- local expl
-
- _description expl user
-
if [[ $OSTYPE = (solaris*|hpux*) ]]; then
- compgen "$expl[@]" -u -S ':' -q
+ _users -S ':' -q
else
- compgen "$expl[@]" -u -S '.' -q
+ _users -S '.' -q
fi
fi
else
diff -u -r oc/User/_dir_list Completion/User/_dir_list
--- oc/User/_dir_list Mon Aug 23 11:28:33 1999
+++ Completion/User/_dir_list Mon Aug 23 10:23:14 1999
@@ -0,0 +1,4 @@
+#autoload
+
+compset -P '*:'
+_files -S: -r ': \t\t\-' -/
diff -u -r oc/User/_exec_funcs Completion/User/_exec_funcs
--- oc/User/_exec_funcs Mon Aug 23 11:28:33 1999
+++ Completion/User/_exec_funcs Mon Aug 23 10:23:14 1999
@@ -0,0 +1,49 @@
+#autoload
+
+# This should be called from `_arguments' or otherwise the calling
+# function has to set up an array named `line' that contains the
+# name of the executable as its seconf element or it has to supply
+# that name as an argument.
+# One option is recognized: `-p' means that we are completing a pair
+# of names separated by a slash.
+
+local cmd pair expl
+
+if [[ "$1" = -p ]]; then
+ pair=yes
+ shift
+fi
+
+if (( $# )); then
+ cmd="$1"
+elif [[ $#line -gt 1 ]]; then
+ cmd="$line[2]"
+else
+ return 1
+fi
+
+if [[ -n "$cmd" ]]; then
+ if [[ "$cmd" = /* ]]; then
+ tmp="$cmd"
+ else
+ tmp="$PWD/$cmd"
+ fi
+
+ if [[ "$tmp" != "$_es_command" ]]; then
+ _es_command="$tmp"
+ _es_funcs=( "${(@)${(@M)${(@f)$(nm $cmd)}:#[^ ]# [tT] ([^_]|_[^_])*}##* }" )
+ fi
+
+ if [[ -n "$pair" ]]; then
+ if compset -P '*/'; then
+ _description expl 'call arc to function'
+ else
+ _description expl 'call arc from function'
+ fi
+ else
+ _description expl function
+ fi
+ compadd -M 'r:|_=* r:|=*' - "$_es_funcs[@]"
+else
+ return 1
+fi
diff -u -r oc/User/_find Completion/User/_find
--- oc/User/_find Mon Aug 23 10:12:58 1999
+++ Completion/User/_find Mon Aug 23 10:23:14 1999
@@ -27,6 +27,5 @@
elif [[ "$prev" = -group ]]; then
_groups
elif [[ "$prev" = -user ]]; then
- _description expl user
- compgen "$expl[@]" -u
+ _users
fi
diff -u -r oc/User/_gprof Completion/User/_gprof
--- oc/User/_gprof Mon Aug 23 11:28:33 1999
+++ Completion/User/_gprof Mon Aug 23 11:29:44 1999
@@ -0,0 +1,12 @@
+#compdef gprof
+
+_arguments -s -{a,b,c,D,h,i,l,L,s,T,v,w,x,y,z} \
+ -{A,C,e,E,f,F,J,n,N,O,p,P,q,Q,Z}:'function name: _exec_funcs' \
+ '-I:directory:_dir_list' \
+ '-d-:debug level:' '-k:function names: _exec_funcs -p' \
+ '-m:minimum execution count:' \
+ ':executable:_files -g *(*)' \
+ ':profile file:_files -g gmon.*' \
+ -- -s '(#--[no-] --)' \
+ '*=name*:function name: _exec_funcs' \
+ '*=dirs*:directory:_dir_list'
diff -u -r oc/User/_rlogin Completion/User/_rlogin
--- oc/User/_rlogin Mon Aug 23 10:12:59 1999
+++ Completion/User/_rlogin Mon Aug 23 10:23:14 1999
@@ -15,5 +15,5 @@
elif [[ CURRENT -eq 3 ]]; then
compadd - -l
else
- compgen "$expl[@]" -S @ -u
+ _users -S @
fi
diff -u -r oc/User/_su Completion/User/_su
--- oc/User/_su Mon Aug 23 10:12:59 1999
+++ Completion/User/_su Mon Aug 23 10:23:15 1999
@@ -1,13 +1,12 @@
#compdef su
-local shell comp name usr base expl
+local shell comp name usr base
[[ $words[2] != - ]]
(( base=$?+2 ))
if [[ CURRENT -eq base ]]; then
- _description expl user
- compgen "$expl[@]" -u && return
+ _users && return
usr=root
elif [[ CURRENT -ge base+1 ]]; then
usr=$words[base]
diff -u -r oc/User/_tar Completion/User/_tar
--- oc/User/_tar Mon Aug 23 10:12:59 1999
+++ Completion/User/_tar Mon Aug 23 10:23:15 1999
@@ -72,7 +72,7 @@
# ...long options after `--'.
- _long_options '--owner*:user:_tilde' \
+ _long_options '--owner*:user:_users' \
'*=(PROG|COMMAND)*:program:_command_names' \
'*=ARCHIVE*:archive: _tar_archive' \
'*=NAME*:file:_files' \
diff -u -r oc/User/_users Completion/User/_users
--- oc/User/_users Mon Aug 23 11:30:03 1999
+++ Completion/User/_users Mon Aug 23 10:23:15 1999
@@ -0,0 +1,6 @@
+#autoload
+
+local expl
+
+_description expl user
+compgen "$@" "$expl[@]" -u
--- Util/completion-style-guide.old Mon Aug 23 11:27:28 1999
+++ Util/completion-style-guide Mon Aug 23 11:25:15 1999
@@ -0,0 +1,44 @@
+For now this is just a list of things one should or shouldn't do.
+
+1) Use the functions `_files' and `_path_files' instead of `compgen'
+ with the `-f', `-/', or `-g' options.
+2) *Never* use `compgen' with the `-s' option. This can always be done
+ by a call to `compadd' which is faster.
+3) Using `compgen' with the `-k' option should only be done if a) the
+ array is already existent or b) it is very large (several hundred
+ or thousend elements). In other cases using `compadd' is faster.
+4) Supply match specifications to `compadd' and `compgen' if there are
+ sensible ones.
+5) Use `_description' when adding matches with `compadd' or
+ `compgen'. Use `_message' in places where no matches can be
+ generated. If you want to add different types of matches, add them
+ with multiple calls to `compadd' or `compgen', supplying different
+ descriptions.
+6) Use helper functions that do option completion for you (like
+ `_arguments' and `_long_options') -- it will make your life much
+ easier.
+7) Use helper functions like `_users' and `_groups' instead of direct
+ calls to `compgen -u' or some ad hoc mechanisms to generate such
+ information. This ensures that user can change the way these things
+ will be completed everywhere by just using their own implementations
+ for these functions.
+8) Make sure that the return value of your functions is correct: zero
+ if matches where added and non-zero if no matches were found.
+ In some cases you'll need to test the value of `$compstate[nmatches]'
+ for this. This should always be done by first saving the old value
+ (`local nm="$compstate[nmatches]"') and later comparing this with
+ the current value after all matches have been added (e.g. by
+ writing `[[ nmm -ne compstate[nmatches] ]]' at the end of your
+ function). This guarantees that your functions will be re-usable
+ because calling functions may rely on the correct return value.
+9) In places where different behaviors may be useful, add a
+ configuration key to allow users to select the behavior they
+ prefer. Names for configuration keys should look like `prefix_name',
+ where `prefix' is the (probably abbreviated) name of your function
+ and `name' describes what can be configured.
+ When testing the values of configuration keys, the empty string
+ should result in the same behavior as if the key were unset. This
+ can be achieved by the test `[[ -n "$compconfig[prefix_name]" ]]'.
+10) When writing helper functions that generate matches, the arguments
+ of these should be given unchanged to `compadd' or `compgen' (if
+ they are not used by the helper function itself).
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author