Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: completion
- X-seq: zsh-workers 7512
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: Re: PATCH: completion
- Date: Fri, 27 Aug 1999 09:03:18 +0200 (MET DST)
- In-reply-to: Tanaka Akira's message of 27 Aug 1999 02:56:35 +0900
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Tanaka Akira wrote:
> In article <199908261220.OAA15915@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>,
> Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx> writes:
>
> > @@ -236,7 +240,11 @@
> > - inopt=yes
> > + if [[ -n "$def" ]]; then
> > + inopt=yes
> > + else
> > + inopt=''
> > + fi
>
> In article <199908261352.PAA16045@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>,
> Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx> writes:
>
> > - inopt=yes
> > + inopt=yes
>
> These two hunks cause conflicts. So I couldn't update _arguments to
> latest.
I have no idea how this happened, sorry.
We could either try this patchlet:
--- oc/Base/_arguments Fri Aug 27 08:58:50 1999
+++ Completion/Base/_arguments Fri Aug 27 08:59:00 1999
@@ -236,11 +236,7 @@
def="$opts[$tmp]"
optbeg="$beg"
argbeg="$beg"
- if [[ -n "$def" ]]; then
- inopt=yes
- else
- inopt=''
- fi
+ inopt=yes
uns="${ws[1][2,-1]}"
opt=''
fi
Or -- in case something else went wrong -- just use the version of
`_arguments' I currently have...
Bye
Sven
#autoload
# Complete the arguments of the current command according to the
# descriptions given as arguments to this function.
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 nargbeg inopt fromrest
# Associative arrays used to collect information about the options.
typeset -A opts dopts odopts
typeset -A oneshot
# Fill the cache if we were called with different arguments.
if [[ "$*" != "$_args_cache_descr" ]]; then
_args_cache_descr="$*"
unset _args_cache_{opts,dopts,odopts,oneshot}
typeset -gA _args_cache_{opts,dopts,odopts,oneshot}
unset _args_cache_{long,single,rest,args,sopts,soptseq,soptseq1}
# See if we are using single-letter options.
if [[ "$1" = -s ]]; then
shift
_args_cache_single=yes
fi
# See if we support long options, too.
nth=$argv[(I)--]
if (( nth )); then
_args_cache_long=( "${(@)argv[nth+1,-1]}" )
_args_cache_long_nth=$(( nth - 1 ))
else
_args_cache_long=()
fi
# Now parse the arguments...
args=()
nth=1
while (( $# )); do
# This describes a one-shot option.
if [[ "$1" = [-+]* ]]; then
if [[ "$1" = *:* ]]; then
# If the option name ends in a `-', the first argument comes
# directly after the option, if it ends in a `+', the first
# argument *may* come directly after the option, otherwise it
# is in the next word.
if [[ "$1" = [^:]##-:* ]]; then
tmp="${${1%%:*}[1,-2]}"
_args_cache_dopts[$tmp]="${1#*:}"
elif [[ "$1" = [^:]##+:* ]]; then
tmp="${${1%%:*}[1,-2]}"
_args_cache_odopts[$tmp]="${1#*:}"
else
tmp="${1%%:*}"
_args_cache_opts[$tmp]="${1#*:}"
fi
else
tmp="$1"
_args_cache_opts[$tmp]=''
fi
_args_cache_oneshot[$tmp]=yes
elif [[ "$1" = \*[-+]* ]]; then
# The same for options that may appear more than once.
if [[ "$1" = *:* ]]; then
if [[ "$1" = [^:]##-:* ]]; then
tmp="${${1[2,-1]%%:*}[1,-2]}"
_args_cache_dopts[$tmp]="${1#*:}"
elif [[ "$1" = [^:]##+:* ]]; then
tmp="${${1[2,-1]%%:*}[1,-2]}"
_args_cache_odopts[$tmp]="${1#*:}"
else
tmp="${1[2,-1]%%:*}"
_args_cache_opts[$tmp]="${1#*:}"
fi
else
tmp="${1[2,-1]}"
_args_cache_opts[$tmp]=''
fi
unset "_args_cache_oneshot[$tmp]"
elif [[ "$1" = \*::* ]]; then
# This is `*:...', describing `all other arguments', with argument
# range restriction.
if [[ "$1" = \*:::* ]]; then
_args_cache_rest="*${1[3,-1]}"
else
_args_cache_rest="$1"
fi
elif [[ "$1" = \*:* ]]; then
# This is `*:...', describing `all other arguments'.
_args_cache_rest="${1[3,-1]}"
elif [[ "$1" = :* ]]; then
# This is `:...', describing `the next argument'.
_args_cache_args[nth++]="${1#*:}"
else
# And this is `n:...', describing the `n'th argument.
_args_cache_args[${1%%:*}]="${1#*:}"
nth=$(( ${1%%:*} + 1 ))
fi
shift
done
if [[ -n "$_args_cache_single" ]]; then
_args_cache_soptseq="${(@j::)${(@M)${(@k)opts[(R)]}:#[-+]?}#[-+]}"
if [[ -n "$_args_cache_soptseq" ]]; then
_args_cache_soptseq="[$_args_cache_soptseq]#"
_args_cache_soptseq1="$_args_cache_soptseq#"
else
_args_cache_soptseq=''
_args_cache_soptseq1=''
fi
_args_cache_sopts="${(@j::)${(@M)${(@k)opts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)dopts}:#[-+]?}#[-+]}${(@j::)${(@M)${(@k)odopts}:#[-+]?}#[-+]}"
else
_args_cache_soptseq=''
_args_cache_soptseq1=''
_args_cache_sopts=''
fi
fi
soptseq="$_args_cache_soptseq"
soptseq1="$_args_cache_soptseq1"
sopts="$_args_cache_sopts"
args=( "$_args_cache_args[@]" )
rest="$_args_cache_rest"
opts=( "${(@kv)_args_cache_opts}" )
dopts=( "${(@kv)_args_cache_dopts}" )
odopts=( "${(@kv)_args_cache_odopts}" )
oneshot=( "${(@kv)_args_cache_oneshot}" )
single="$_args_cache_single"
long=( "$_args_cache_long[@]" )
argv=( "${(@)argv[1,_args_cache_long_nth]}" )
# Parse the command line...
ws=( "${(@)words[2,-1]}" )
cur=$(( CURRENT-2 ))
nth=1
line=( "$words[1]" )
beg=2
argbeg=1
optbeg=1
nargbeg=1
# ...until the current word is reached.
while [[ cur -gt 0 ]]; do
# `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=''
# 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" && "$def" != \** ]]; then
if [[ "$def" = ?*[^\\]:*[^\\]:* ]]; then
def="${def#?*[^\\]:*[^\\]:}"
argbeg="$beg"
else
def=''
fi
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
# we test for options below and handle normal arguments.
if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
opt=yes
arg=yes
else
def=''
fi
fi
if [[ -n "$opt" ]]; 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.
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]]"
optbeg="$beg"
argbeg="$beg"
inopt=yes
[[ -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]"
optbeg="$beg"
argbeg="$beg"
inopt=yes
uns="${ws[1][2,-1]}"
opt=''
fi
fi
# 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
fi
shift 1 tmp
done
if (( $#tmp )); then
# 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]]"
optbeg="$beg"
argbeg="$beg"
inopt=yes
[[ -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
elif [[ "$ws[1]" = ${tmp[1]}* ]]; then
break
fi
shift 1 tmp
done
if (( $#tmp )); then
opt=''
def="$odopts[$tmp[1]]"
optbeg="$beg"
argbeg="$beg"
inopt=yes
[[ -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#?*[^\\]:*[^\\]:}"
optbeg="$beg"
argbeg="$beg"
else
def=''
fi
fi
fi
fi
[[ -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]]#[-+]}}"
tmp=(
"opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]"
"dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]"
"odopts[${(@)^odopts[(I)${ws[1][1]}[$uns]]}]"
)
(( $#tmp )) && unset "$tmp[@]"
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 [[ -n "$opt" && -n "$arg" ]]; then
def=''
line=( "$line[@]" "$ws[1]" )
[[ -n "$inopt" ]] && nargbeg=$(( beg - 1 ))
inopt=''
(( nth++ ))
fi
fi
fi
shift 1 ws
(( cur-- ))
(( beg++ ))
done
[[ -n "$inopt" ]] && nargbeg=$(( beg - 1 ))
# Now generate the matches.
if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
# If the current words starts with `--' and we should use long
# options, just call...
_long_options "$long[@]"
else
nm="$compstate[nmatches]"
if [[ -z "$def" || "$def" = :* ]]; then
local pre="$PREFIX"
uns=''
# We either don't have a description for an argument of an option
# or we have a description for a optional argument.
if [[ -z "$def" ]]; then
# If we have none at all, use the one for this argument position.
def="$args[nth]"
if [[ -z "$def" ]]; then
def="$rest"
optbeg="$nargbeg"
argbeg="$nargbeg"
fromrest=yes
fi
fi
# In any case, we have to complete option names here, but we may
# be in a string that starts with an option name and continues with
# the first argument, test that (again, two loops).
opt=yes
if (( $#dopts )); then
# Get the option names.
tmp=( "${(@k)dopts}" )
prefix="$PREFIX"
while (( $#tmp )); do
if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
def="$dopts[$tmp[1]]"
opt=''
uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
break
elif compset -P "$tmp[1]"; then
# The current string starts with the option name, so ignore
# that and complete the rest of the string.
def="$dopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
if [[ -n "$opt" && $#odopts -ne 0 ]]; then
tmp=( "${(@k)odopts}" )
prefix="$PREFIX"
while (( $#tmp )); do
if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then
def="$odopts[$tmp[1]]"
opt=''
uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}"
break
elif compset -P "$tmp[1]"; then
def="$odopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
[[ -n "$sopts" && -n "$opt" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]] && \
uns="${PREFIX[2,-1]}"
if [[ -n "$uns" ]]; then
uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}"
tmp=(
"opts[${(@)^opts[(I)${pre[1]}[$uns]]}]"
"dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]"
"odopts[${(@)^odopts[(I)${pre[1]}[$uns]]}]"
)
(( $#tmp )) && unset "$tmp[@]"
fi
if [[ -n "$opt" && ( "$def" != \** ||
( -n "$fromrest" && CURRENT -eq argbeg+1 ) ) ]]; then
# We aren't in an argument directly after a option name, so
# all option names are possible matches.
if [[ "$compconfig[option_prefix]" != *(short|all)* ||
"$PREFIX" = [-+]* ]]; then
_description expl option
if [[ -n "$sopts" && -n "$PREFIX" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then
if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then
compadd "$expl[@]" -Q \
-y "( ${(j: :)${(@M)${(@k)opts}:#[-+]?}} ${(j: :)${(@M)${(@k)dopts}:#[-+]?}} ${(j: :)${(@M)${(@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
fi
else
compadd "$expl[@]" -Q - "${(@k)opts}" "${(@k)odopts}" && ret=0
compadd "$expl[@]" -QS '' - "${(@k)dopts}" && ret=0
fi
fi
[[ $#long -ne 0 &&
( "$compconfig[option_prefix]" != *(long|all)* ||
"$PREFIX" = --* ) ]] && \
_long_options "$long[@]" && ret=0
fi
fi
# Now add the matches from the description, if any.
if [[ -n "$def" ]]; then
# 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
[[ beg -ge $#words ]] && beg=$(( $#words - 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="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}"
if [[ "$def" = *[^\\]:*[^\\]:* ]]; then
action="${${${(M)${def#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}"
else
action="${${def#*[^\\]:}//\\\\:/:}"
fi
_description expl "$descr"
if [[ -z "$action" ]]; then
# An empty action means that we should just display a message.
_message "$descr"
return ret
elif [[ "$action" = \(*\) ]]; 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.
${(e)=~action}
else
# Otherwise we call it with the description-arguments built above.
action=( $=action )
${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
fi
fi
# Set the return value.
[[ nm -ne "$compstate[nmatches]" ]]
fi
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author