mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-20 05:53:52 +01:00
moved to Completion/Base/Utility/_arguments
This commit is contained in:
parent
1d860e140e
commit
fd0f0d4598
@ -1,409 +0,0 @@
|
||||
#autoload
|
||||
|
||||
# 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 oldcontext="$curcontext" hasopts rawret
|
||||
|
||||
long=$argv[(I)--]
|
||||
if (( long )); then
|
||||
local name tmp tmpargv
|
||||
|
||||
if [[ long -eq 1 ]]; then
|
||||
tmpargv=()
|
||||
else
|
||||
tmpargv=( "${(@)argv[1,long-1]}" )
|
||||
fi
|
||||
|
||||
name=${~words[1]}
|
||||
[[ "$name" = [^/]*/* ]] && name="$PWD/$name"
|
||||
|
||||
name="_args_cache_${name}"
|
||||
name="${name//[^a-zA-Z0-9_]/_}"
|
||||
|
||||
if (( ! ${(P)+name} )); then
|
||||
local iopts sopts pattern tmpo dir cur cache
|
||||
typeset -U lopts
|
||||
|
||||
cache=()
|
||||
|
||||
# We have to build a new long-option cache, get the `-i' and
|
||||
# `-s' options.
|
||||
|
||||
set -- "${(@)argv[long+1,-1]}"
|
||||
|
||||
iopts=()
|
||||
sopts=()
|
||||
while [[ "$1" = -[is]* ]]; do
|
||||
if [[ "$1" = -??* ]]; then
|
||||
tmp="${1[3,-1]}"
|
||||
cur=1
|
||||
else
|
||||
tmp="$2"
|
||||
cur=2
|
||||
fi
|
||||
if [[ "$tmp[1]" = '(' ]]; then
|
||||
tmp=( ${=tmp[2,-2]} )
|
||||
else
|
||||
tmp=( "${(@P)tmp}" )
|
||||
fi
|
||||
if [[ "$1" = -i* ]]; then
|
||||
iopts=( "$iopts[@]" "$tmp[@]" )
|
||||
else
|
||||
sopts=( "$sopts[@]" "$tmp[@]" )
|
||||
fi
|
||||
shift cur
|
||||
done
|
||||
|
||||
# Now get the long option names by calling the command with `--help'.
|
||||
# The parameter expansion trickery first gets the lines as separate
|
||||
# array elements. Then we select all lines whose first non-blank
|
||||
# character is a hyphen. Since some commands document more than one
|
||||
# option per line, separated by commas, we convert commas into
|
||||
# newlines and then split the result again at newlines after joining
|
||||
# the old array elements with newlines between them. Then we select
|
||||
# those elements that start with two hyphens, remove anything up to
|
||||
# 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 options ${~words[1]} --help 2>&1)//\[--/
|
||||
--}:#[ ]#-*}//,/
|
||||
}}:#[ ]#--*}#*--}%%[] ]*}:#}")
|
||||
|
||||
# Remove options also described by user-defined specs.
|
||||
|
||||
tmp=()
|
||||
for opt in "${(@)lopts:#--}"; do
|
||||
|
||||
# Using (( ... )) gives a parse error.
|
||||
|
||||
let "$tmpargv[(I)(|\([^\)]#\))(|\*)${opt}(|[-+=])(|\[*\])(|:*)]" ||
|
||||
tmp=( "$tmp[@]" "$opt" )
|
||||
done
|
||||
lopts=( "$tmp[@]" )
|
||||
|
||||
# Now remove all ignored options ...
|
||||
|
||||
while (( $#iopts )); do
|
||||
lopts=( ${lopts:#$~iopts[1]} )
|
||||
shift iopts
|
||||
done
|
||||
|
||||
# ... and add "same" options
|
||||
|
||||
while (( $#sopts )); do
|
||||
lopts=( $lopts ${lopts/$~sopts[1]/$sopts[2]} )
|
||||
shift 2 sopts
|
||||
done
|
||||
|
||||
# Then we walk through the descriptions plus a few builtin ones.
|
||||
# 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 -/' '*: : '
|
||||
|
||||
while (( $# )); do
|
||||
|
||||
# First, we get the pattern and the action to use and take them
|
||||
# from the positional parameters.
|
||||
|
||||
pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
|
||||
descr="${1#${pattern}}"
|
||||
if [[ "$pattern" = *\(-\) ]]; then
|
||||
pattern="$pattern[1,-4]"
|
||||
dir=-
|
||||
else
|
||||
dir=
|
||||
fi
|
||||
shift
|
||||
|
||||
# We get all options matching the pattern and take them from the
|
||||
# list we have built. If no option matches the pattern, we
|
||||
# continue with the next.
|
||||
|
||||
tmp=("${(@M)lopts:##$~pattern}")
|
||||
lopts=("${(@)lopts:##$~pattern}")
|
||||
|
||||
(( $#tmp )) || continue
|
||||
|
||||
opt=''
|
||||
|
||||
# If there are option strings with a `[=', we take these to get an
|
||||
# optional argument.
|
||||
|
||||
tmpo=("${(@M)tmp:#*\[\=*}")
|
||||
if (( $#tmpo )); then
|
||||
tmp=("${(@)tmp:#*\[\=*}")
|
||||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||
|
||||
if [[ "$descr" = ::* ]]; then
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||
else
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}:${descr}" )
|
||||
fi
|
||||
fi
|
||||
|
||||
# Descriptions with `=': mandatory argument.
|
||||
|
||||
tmpo=("${(@M)tmp:#*\=*}")
|
||||
if (( $#tmpo )); then
|
||||
tmp=("${(@)tmp:#*\=*}")
|
||||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||
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-]}")
|
||||
if [[ -n "$descr" && "$descr" != ': : ' ]]; then
|
||||
cache=( "$cache[@]" "${(@)^tmp}${descr}" )
|
||||
else
|
||||
cache=( "$cache[@]" "$tmp[@]" )
|
||||
fi
|
||||
fi
|
||||
done
|
||||
set -A "$name" "${(@)cache:# #}"
|
||||
fi
|
||||
set -- "$tmpargv[@]" "${(@P)name}"
|
||||
fi
|
||||
|
||||
subopts=()
|
||||
while [[ "$1" = -(O*|[CR]) ]]; do
|
||||
case "$1" in
|
||||
-C) usecc=yes; shift ;;
|
||||
-O) subopts=( "${(@P)2}" ); shift 2 ;;
|
||||
-O*) subopts=( "${(@P)1[3,-1]}" ); shift ;;
|
||||
-R) rawret=yes; shift;;
|
||||
esac
|
||||
done
|
||||
|
||||
zstyle -s ":completion:${curcontext}:options" auto-description autod
|
||||
|
||||
if (( $# )) && comparguments -i "$autod" "$@"; then
|
||||
local action noargs aret expl local tried
|
||||
local next direct odirect equal single matcher matched ws tmp1 tmp2 tmp3
|
||||
local opts subc tc prefix suffix descrs actions subcs anum
|
||||
local origpre="$PREFIX" origipre="$IPREFIX" nm="$compstate[nmatches]"
|
||||
|
||||
if comparguments -D descrs actions subcs; then
|
||||
if comparguments -O next direct odirect equal; then
|
||||
opts=yes
|
||||
_tags "$subcs[@]" options
|
||||
else
|
||||
_tags "$subcs[@]"
|
||||
fi
|
||||
else
|
||||
if comparguments -a; then
|
||||
noargs='no more arguments'
|
||||
else
|
||||
noargs='no arguments'
|
||||
fi
|
||||
if comparguments -O next direct odirect equal; then
|
||||
opts=yes
|
||||
_tags options
|
||||
elif [[ $? -eq 2 ]]; then
|
||||
compadd -Q - "${PREFIX}${SUFFIX}"
|
||||
return 0
|
||||
else
|
||||
_message "$noargs"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
comparguments -M matcher
|
||||
|
||||
context=()
|
||||
state=()
|
||||
|
||||
while true; do
|
||||
while _tags; do
|
||||
anum=1
|
||||
while [[ anum -le $#descrs ]]; do
|
||||
|
||||
action="$actions[anum]"
|
||||
descr="$descrs[anum]"
|
||||
subc="$subcs[anum++]"
|
||||
|
||||
if [[ -n "$matched" ]] || _requested "$subc"; then
|
||||
|
||||
curcontext="${oldcontext%:*}:$subc"
|
||||
|
||||
_description "$subc" expl "$descr"
|
||||
|
||||
if [[ "$action" = \=\ * ]]; then
|
||||
action="$action[3,-1]"
|
||||
words=( "$subc" "$words[@]" )
|
||||
(( CURRENT++ ))
|
||||
fi
|
||||
|
||||
if [[ "$action" = -\>* ]]; then
|
||||
action="${${action[3,-1]##[ ]#}%%[ ]#}"
|
||||
if (( ! $state[(I)$action] )); then
|
||||
comparguments -W line opt_args
|
||||
state=( "$state[@]" "$action" )
|
||||
if [[ -n "$usecc" ]]; then
|
||||
curcontext="${oldcontext%:*}:$subc"
|
||||
else
|
||||
context=( "$context[@]" "$subc" )
|
||||
fi
|
||||
compstate[restore]=''
|
||||
aret=yes
|
||||
fi
|
||||
else
|
||||
if [[ -z "$local" ]]; then
|
||||
local line
|
||||
typeset -A opt_args
|
||||
local=yes
|
||||
fi
|
||||
|
||||
comparguments -W line opt_args
|
||||
|
||||
if [[ "$action" = \ # ]]; then
|
||||
|
||||
# An empty action means that we should just display a message.
|
||||
|
||||
_message "$descr"
|
||||
mesg=yes
|
||||
tried=yes
|
||||
|
||||
elif [[ "$action" = \(\(*\)\) ]]; then
|
||||
|
||||
# ((...)) contains literal strings with descriptions.
|
||||
|
||||
eval ws\=\( "${action[3,-3]}" \)
|
||||
|
||||
_describe -t "$subc" "$descr" ws -M "$matcher" "$subopts[@]"
|
||||
tried=yes
|
||||
|
||||
elif [[ "$action" = \(*\) ]]; then
|
||||
|
||||
# Anything inside `(...)' is added directly.
|
||||
|
||||
eval ws\=\( "${action[2,-2]}" \)
|
||||
|
||||
_all_labels "$subc" expl "$descr" compadd "$subopts[@]" -a - ws
|
||||
tried=yes
|
||||
elif [[ "$action" = \{*\} ]]; then
|
||||
|
||||
# A string in braces is evaluated.
|
||||
|
||||
while _next_label "$subc" expl "$descr"; do
|
||||
eval "$action[2,-2]"
|
||||
done
|
||||
tried=yes
|
||||
elif [[ "$action" = \ * ]]; then
|
||||
|
||||
# If the action starts with a space, we just call it.
|
||||
|
||||
eval "action=( $action )"
|
||||
while _next_label "$subc" expl "$descr"; do
|
||||
"$action[@]"
|
||||
done
|
||||
tried=yes
|
||||
else
|
||||
|
||||
# Otherwise we call it with the description-arguments.
|
||||
|
||||
eval "action=( $action )"
|
||||
while _next_label "$subc" expl "$descr"; do
|
||||
"$action[1]" "$subopts[@]" "$expl[@]" "${(@)action[2,-1]}"
|
||||
done
|
||||
tried=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "$matched$hasopts" && ( -z "$aret" || "$PREFIX" = "$origpre" ) ]] &&
|
||||
_requested options &&
|
||||
{ ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
|
||||
[[ "$origpre" = [-+]* || -z "$aret$mesg$tried" ]] } ; then
|
||||
local prevpre="$PREFIX" previpre="$IPREFIX"
|
||||
|
||||
hasopts=yes
|
||||
|
||||
PREFIX="$origpre"
|
||||
IPREFIX="$origipre"
|
||||
|
||||
if comparguments -s single; then
|
||||
|
||||
if [[ "$single" = direct ]]; then
|
||||
_all_labels options expl option \
|
||||
compadd -QS '' - "${PREFIX}${SUFFIX}"
|
||||
elif [[ "$single" = next ]]; then
|
||||
_all_labels options expl option \
|
||||
compadd -Q - "${PREFIX}${SUFFIX}"
|
||||
elif [[ "$single" = equal ]]; then
|
||||
_all_labels options expl option \
|
||||
compadd -QqS= - "${PREFIX}${SUFFIX}"
|
||||
else
|
||||
tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
|
||||
[[ "$PREFIX" != --* ]] && tmp1=( "${(@)tmp1:#--*}" )
|
||||
tmp3=( "${(M@)tmp1:#[-+]?[^:]*}" )
|
||||
tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
|
||||
tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
|
||||
|
||||
_describe -o option \
|
||||
tmp1 tmp2 -Q -S '' -- \
|
||||
tmp3 -Q
|
||||
fi
|
||||
single=yes
|
||||
else
|
||||
next=( "$next[@]" "$odirect[@]" )
|
||||
_describe -o option \
|
||||
next -Q -M "$matcher" -- \
|
||||
direct -QS '' -M "$matcher" -- \
|
||||
equal -QqS= -M "$matcher"
|
||||
fi
|
||||
PREFIX="$prevpre"
|
||||
IPREFIX="$previpre"
|
||||
fi
|
||||
[[ -n "$tried" && "$PREFIX" != [-+]* ]] && break
|
||||
done
|
||||
if [[ -n "$opts" && -z "$aret$matched$mesg" &&
|
||||
nm -eq compstate[nmatches] ]]; then
|
||||
|
||||
PREFIX="$origpre"
|
||||
IPREFIX="$origipre"
|
||||
|
||||
prefix="${PREFIX#*\=}"
|
||||
suffix="$SUFFIX"
|
||||
PREFIX="${PREFIX%%\=*}"
|
||||
SUFFIX=''
|
||||
|
||||
compadd -M "$matcher" -D equal - "${(@)equal%%:*}"
|
||||
|
||||
if [[ $#equal -eq 1 ]]; then
|
||||
PREFIX="$prefix"
|
||||
SUFFIX="$suffix"
|
||||
IPREFIX="${IPREFIX}${equal[1]%%:*}="
|
||||
matched=yes
|
||||
|
||||
comparguments -L "${equal[1]%%:*}" descrs actions subcs
|
||||
|
||||
_tags "$subcs[@]"
|
||||
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
[[ -z "$aret" || -z "$usecc" ]] && curcontext="$oldcontext"
|
||||
|
||||
if [[ -n "$aret" ]]; then
|
||||
[[ -n $rawret ]] && return 300
|
||||
else
|
||||
[[ -n "$noargs" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
|
||||
fi
|
||||
# Set the return value.
|
||||
|
||||
[[ nm -ne "$compstate[nmatches]" ]]
|
||||
else
|
||||
return 1
|
||||
fi
|
Loading…
Reference in New Issue
Block a user