mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-03 20:20:56 +02:00
pat(-) in long-option patterns to say that argument should be completed only after the `='; merge _arguments and _argument_sets; slightly better test when not to complete options (11489)
This commit is contained in:
parent
007cfdff55
commit
ce90081ea8
5 changed files with 424 additions and 379 deletions
|
@ -1,5 +1,10 @@
|
||||||
2000-05-22 Sven Wischnowsky <wischnow@zsh.org>
|
2000-05-22 Sven Wischnowsky <wischnow@zsh.org>
|
||||||
|
|
||||||
|
* 11489: Completion/Base/_arguments, Doc/Zsh/compsys.yo,
|
||||||
|
Src/Zle/computil.c: pat(-) in long-option patterns to say that
|
||||||
|
argument should be completed only after the `='; merge _arguments
|
||||||
|
and _argument_sets; slightly better test when not to complete options
|
||||||
|
|
||||||
* 11487: Completion/Core/_expand, Src/Zle/complist.c: fix for
|
* 11487: Completion/Core/_expand, Src/Zle/complist.c: fix for
|
||||||
a-a-m-c in menu selection; scroll explanations onto screen again
|
a-a-m-c in menu selection; scroll explanations onto screen again
|
||||||
when cursor comes near them
|
when cursor comes near them
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
#autoload
|
|
||||||
|
|
||||||
local all ret=1 end xor has_args had_args ostate ocontext oopt_args r
|
|
||||||
local nm="$compstate[nmatches]"
|
|
||||||
local opre="$PREFIX" oipre="$IPREFIX" ocur="$CURRENT"
|
|
||||||
local osuf="$SUFFIX" oisuf="$ISUFFIX" owords
|
|
||||||
local _ms_match _ms_opt _ms_soptmid _ms_soptmidadd _ms_soptend
|
|
||||||
local _ms_optnext _ms_optdirect _ms_optequal
|
|
||||||
|
|
||||||
_ms_soptmid=()
|
|
||||||
_ms_soptmidadd=()
|
|
||||||
_ms_soptend=()
|
|
||||||
_ms_optnext=()
|
|
||||||
_ms_optdirect=()
|
|
||||||
_ms_optequal=()
|
|
||||||
|
|
||||||
owords=("$words[@]")
|
|
||||||
|
|
||||||
end=$argv[(i)-]
|
|
||||||
[[ end -gt $# ]] && return 1
|
|
||||||
|
|
||||||
all=( "${(@)argv[1,end]}" )
|
|
||||||
|
|
||||||
shift end
|
|
||||||
|
|
||||||
xor=()
|
|
||||||
ostate=()
|
|
||||||
ocontext=()
|
|
||||||
oopt_args=()
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
end=$argv[(i)-]
|
|
||||||
|
|
||||||
if [[ "$1" = \(*\) ]]; then
|
|
||||||
_arguments -m xor "${1[2,-2]}" "$all[@]" \
|
|
||||||
"$1${(@)^argv[2,end-1]:#\(*}" \
|
|
||||||
"${1[1,-2]} ${(@)${(@M)^argv[2,end-1]:#\(*}#?}"
|
|
||||||
else
|
|
||||||
_arguments -m xor "$1" "$all[@]" "${(@)argv[2,end-1]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
r=$?
|
|
||||||
|
|
||||||
oopt_args=( "$oopt_args[@]" "${(@kv)opt_args}" )
|
|
||||||
if [[ r -eq 300 ]]; then
|
|
||||||
ret=300
|
|
||||||
ostate=( "$ostate[@]" "$state[@]" )
|
|
||||||
ocontext=( "$ocontext[@]" "$context[@]" )
|
|
||||||
PREFIX="$opre" SUFFIX="$osuf"
|
|
||||||
IPREFIX="$oipre" ISUFFIX="$oisuf"
|
|
||||||
CURRENT="$ocur" words=( "$owords[@]" )
|
|
||||||
elif [[ "$r$ret" = 01 ]]; then
|
|
||||||
ret=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ end -gt $# ]] && break
|
|
||||||
|
|
||||||
shift end
|
|
||||||
done
|
|
||||||
|
|
||||||
[[ -n "$_ms_opt" ]] &&
|
|
||||||
{ ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
|
|
||||||
[[ "$PREFIX" = [-+]* ||
|
|
||||||
( -z "$has_args" && ret -ne 300 && nm -eq compstate[nmatches] ) ]] } &&
|
|
||||||
has_args=yes &&
|
|
||||||
_describe -o option \
|
|
||||||
_ms_soptmid _ms_soptmidadd -Q -S '' -- \
|
|
||||||
_ms_soptend -Q -- \
|
|
||||||
_ms_optnext -Q -M "$_ms_match" -- \
|
|
||||||
_ms_optdirect -QS '' -M "$_ms_match" -- \
|
|
||||||
_ms_optequal -QqS= -M "$_ms_match" && [[ ret -eq 1 ]] && ret=0
|
|
||||||
|
|
||||||
opt_args=( "$oopt_args[@]" )
|
|
||||||
|
|
||||||
if [[ ret -eq 300 ]]; then
|
|
||||||
state=( "$ostate[@]" )
|
|
||||||
context=( "$ocontext[@]" )
|
|
||||||
elif [[ -z "$has_args" ]]; then
|
|
||||||
if [[ -n "$had_args" ]]; then
|
|
||||||
_message "no more arguments"
|
|
||||||
else
|
|
||||||
_message "no arguments"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
return ret
|
|
|
@ -4,7 +4,7 @@
|
||||||
# descriptions given as arguments to this function.
|
# descriptions given as arguments to this function.
|
||||||
|
|
||||||
local long cmd="$words[1]" descr mesg subopts opt usecc autod
|
local long cmd="$words[1]" descr mesg subopts opt usecc autod
|
||||||
local oldcontext="$curcontext" hasopts multi ismulti
|
local oldcontext="$curcontext" hasopts
|
||||||
|
|
||||||
long=$argv[(I)--]
|
long=$argv[(I)--]
|
||||||
if (( long )); then
|
if (( long )); then
|
||||||
|
@ -23,7 +23,7 @@ if (( long )); then
|
||||||
name="${name//[^a-zA-Z0-9_]/_}"
|
name="${name//[^a-zA-Z0-9_]/_}"
|
||||||
|
|
||||||
if (( ! ${(P)+name} )); then
|
if (( ! ${(P)+name} )); then
|
||||||
local iopts sopts pattern tmpo cur cache
|
local iopts sopts pattern tmpo dir cur cache
|
||||||
typeset -U lopts
|
typeset -U lopts
|
||||||
|
|
||||||
cache=()
|
cache=()
|
||||||
|
@ -98,6 +98,12 @@ if (( long )); then
|
||||||
|
|
||||||
pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
|
pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
|
||||||
descr="${1#${pattern}}"
|
descr="${1#${pattern}}"
|
||||||
|
if [[ "$pattern" = *\(-\) ]]; then
|
||||||
|
pattern="$pattern[1,-4]"
|
||||||
|
dir=-
|
||||||
|
else
|
||||||
|
dir=
|
||||||
|
fi
|
||||||
shift
|
shift
|
||||||
|
|
||||||
# We get all options matching the pattern and take them from the
|
# We get all options matching the pattern and take them from the
|
||||||
|
@ -111,7 +117,7 @@ if (( long )); then
|
||||||
|
|
||||||
opt=''
|
opt=''
|
||||||
|
|
||||||
# If there are option strings with a `[=', we take these get an
|
# If there are option strings with a `[=', we take these to get an
|
||||||
# optional argument.
|
# optional argument.
|
||||||
|
|
||||||
tmpo=("${(@M)tmp:#*\[\=*}")
|
tmpo=("${(@M)tmp:#*\[\=*}")
|
||||||
|
@ -120,9 +126,9 @@ if (( long )); then
|
||||||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||||
|
|
||||||
if [[ "$descr" = ::* ]]; then
|
if [[ "$descr" = ::* ]]; then
|
||||||
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
|
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||||
else
|
else
|
||||||
cache=( "$cache[@]" "${(@)^tmpo}=:${descr}" )
|
cache=( "$cache[@]" "${(@)^tmpo}=${dir}:${descr}" )
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -133,10 +139,10 @@ if (( long )); then
|
||||||
tmp=("${(@)tmp:#*\=*}")
|
tmp=("${(@)tmp:#*\=*}")
|
||||||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||||
|
|
||||||
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
|
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Everything else is just added as a option without arguments.
|
# Everything else is just added as an option without arguments.
|
||||||
|
|
||||||
if (( $#tmp )); then
|
if (( $#tmp )); then
|
||||||
tmp=("${(@)tmp//[^a-zA-Z0-9-]}")
|
tmp=("${(@)tmp//[^a-zA-Z0-9-]}")
|
||||||
|
@ -148,27 +154,22 @@ if (( long )); then
|
||||||
set -- "$tmpargv[@]" "${(@P)name}"
|
set -- "$tmpargv[@]" "${(@P)name}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
multi=(-i)
|
|
||||||
subopts=()
|
subopts=()
|
||||||
while [[ "$1" = -(O*|C|m*) ]]; do
|
while [[ "$1" = -(O*|C|m*) ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-C) usecc=yes; shift ;;
|
-C) usecc=yes; shift ;;
|
||||||
-O) subopts=( "${(@P)2}" ); shift 2 ;;
|
-O) subopts=( "${(@P)2}" ); shift 2 ;;
|
||||||
-O*) subopts=( "${(@P)1[3,-1]}" ); shift ;;
|
-O*) subopts=( "${(@P)1[3,-1]}" ); shift ;;
|
||||||
-m) ismulti=yes multi=(-I "$2" "$3"); shift 3 ;;
|
|
||||||
-m*) ismulti=yes multi=(-I "${1[3,-1]}" "$2"); shift 2 ;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
zstyle -s ":completion:${curcontext}:options" auto-description autod
|
zstyle -s ":completion:${curcontext}:options" auto-description autod
|
||||||
|
|
||||||
if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
if (( $# )) && comparguments -i "$autod" "$@"; then
|
||||||
local action noargs aret expl local tried
|
local action noargs aret expl local tried
|
||||||
local next direct odirect equal single matcher matched ws tmp1 tmp2 tmp3
|
local next direct odirect equal single matcher matched ws tmp1 tmp2 tmp3
|
||||||
local opts subc tc prefix suffix descrs actions subcs
|
local opts subc tc prefix suffix descrs actions subcs
|
||||||
local origpre="$PREFIX" origipre="$IPREFIX"
|
local origpre="$PREFIX" origipre="$IPREFIX" nm="$compstate[nmatches]"
|
||||||
|
|
||||||
[[ -z "$ismulti" ]] && local nm="$compstate[nmatches]"
|
|
||||||
|
|
||||||
if comparguments -D descrs actions subcs; then
|
if comparguments -D descrs actions subcs; then
|
||||||
if comparguments -O next direct odirect equal; then
|
if comparguments -O next direct odirect equal; then
|
||||||
|
@ -180,7 +181,6 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
||||||
else
|
else
|
||||||
if comparguments -a; then
|
if comparguments -a; then
|
||||||
noargs='no more arguments'
|
noargs='no more arguments'
|
||||||
had_args=yes
|
|
||||||
else
|
else
|
||||||
noargs='no arguments'
|
noargs='no arguments'
|
||||||
fi
|
fi
|
||||||
|
@ -299,8 +299,7 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ -z "$matched$hasopts" ]] && _requested options &&
|
if [[ -z "$matched$hasopts" ]] && _requested options &&
|
||||||
{ [[ -n "$ismulti" ]] ||
|
{ ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
|
||||||
! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
|
|
||||||
[[ "$origpre" = [-+]* || -z "$aret$mesg$tried" ]] } ; then
|
[[ "$origpre" = [-+]* || -z "$aret$mesg$tried" ]] } ; then
|
||||||
local prevpre="$PREFIX" previpre="$IPREFIX"
|
local prevpre="$PREFIX" previpre="$IPREFIX"
|
||||||
|
|
||||||
|
@ -326,37 +325,22 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
||||||
tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
|
tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
|
||||||
tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
|
tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
|
||||||
|
|
||||||
if [[ -n "$ismulti" ]]; then
|
_describe -o option \
|
||||||
_ms_opt=yes
|
tmp1 tmp2 -Q -S '' -- \
|
||||||
_ms_soptmid=( "$_ms_soptmid[@]" "$tmp1[@]" )
|
tmp3 -Q
|
||||||
_ms_soptmidadd=( "$_ms_soptmidadd[@]" "$tmp2[@]" )
|
|
||||||
_ms_soptend=( "$_ms_soptend[@]" "$tmp3[@]" )
|
|
||||||
else
|
|
||||||
_describe -o option \
|
|
||||||
tmp1 tmp2 -Q -S '' -- \
|
|
||||||
tmp3 -Q
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
single=yes
|
single=yes
|
||||||
else
|
else
|
||||||
next=( "$next[@]" "$odirect[@]" )
|
next=( "$next[@]" "$odirect[@]" )
|
||||||
if [[ -n "$ismulti" ]]; then
|
_describe -o option \
|
||||||
_ms_opt=yes
|
next -Q -M "$matcher" -- \
|
||||||
_ms_match="$_ms_match $matcher"
|
direct -QS '' -M "$matcher" -- \
|
||||||
_ms_optnext=( "$_ms_optnext[@]" "$next[@]" )
|
equal -QqS= -M "$matcher"
|
||||||
_ms_optdirect=( "$_ms_optdirect[@]" "$direct[@]" )
|
|
||||||
_ms_optequal=( "$_ms_optequal[@]" "$equal[@]" )
|
|
||||||
else
|
|
||||||
_describe -o option \
|
|
||||||
next -Q -M "$matcher" -- \
|
|
||||||
direct -QS '' -M "$matcher" -- \
|
|
||||||
equal -QqS= -M "$matcher"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
PREFIX="$prevpre"
|
PREFIX="$prevpre"
|
||||||
IPREFIX="$previpre"
|
IPREFIX="$previpre"
|
||||||
fi
|
fi
|
||||||
[[ -n "$tried" ]] && break
|
[[ -n "$tried" && "$PREFIX" != [-+]* ]] && break
|
||||||
done
|
done
|
||||||
if [[ -n "$opts" && -z "$aret$matched$mesg" &&
|
if [[ -n "$opts" && -z "$aret$matched$mesg" &&
|
||||||
nm -eq compstate[nmatches] ]]; then
|
nm -eq compstate[nmatches] ]]; then
|
||||||
|
@ -391,11 +375,7 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
||||||
|
|
||||||
[[ -n "$aret" ]] && return 300
|
[[ -n "$aret" ]] && return 300
|
||||||
|
|
||||||
if [[ -n "$noargs" ]]; then
|
[[ -n "$noargs" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
|
||||||
[[ -z "$ismulti" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
|
|
||||||
else
|
|
||||||
has_args=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set the return value.
|
# Set the return value.
|
||||||
|
|
||||||
|
|
|
@ -2756,6 +2756,45 @@ Also, during the evaluation of the var(action), the context name in
|
||||||
the tt(curcontext) parameter will be changed by appending the same
|
the tt(curcontext) parameter will be changed by appending the same
|
||||||
string that is stored in the tt(context) parameter.
|
string that is stored in the tt(context) parameter.
|
||||||
|
|
||||||
|
The aruments also allows to specify multiple sets of options and
|
||||||
|
arguments separated by single hyphens. The specifications before
|
||||||
|
the first hyphen are shared by all sets given after the first
|
||||||
|
hyphen. The first word in every other set gives the name of the
|
||||||
|
set. This name may appear in exclusion lists in the specifications,
|
||||||
|
either alone or before one of the possible values described above
|
||||||
|
(with a `tt(-)' between the name and the rest).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
example(_argument_sets \
|
||||||
|
-a \
|
||||||
|
- set1 \
|
||||||
|
-c \
|
||||||
|
- set2 \
|
||||||
|
-d \
|
||||||
|
':arg:(x2 y2)')
|
||||||
|
|
||||||
|
This defines two sets. When the command line contains the option
|
||||||
|
`tt(-c)', the `tt(-d)' option and the argument will not be considered
|
||||||
|
possible completions. When it contains `tt(-d)' or an argument, the
|
||||||
|
option `tt(-c)' will not be completed any more, but if `tt(-a)' is
|
||||||
|
given, both sets will still be considered valid, because it appears
|
||||||
|
before the first hyphen, so both sets contain this option.
|
||||||
|
|
||||||
|
If the name-string is of the form `tt(LPAR())var(name)tt(RPAR())' then
|
||||||
|
all specifications in the set have an implicit exclusion list
|
||||||
|
containing the name of the set, i.e. all specifications are mutual
|
||||||
|
exclusive with all other specifications in the same set. This is
|
||||||
|
useful for defining multiple sets of options which are mutually
|
||||||
|
exclusive and in which the options are aliases for each other. E.g.:
|
||||||
|
|
||||||
|
example(_argument_sets \
|
||||||
|
-a -b \
|
||||||
|
- '(compress)' \
|
||||||
|
{-c,--compress}'[compress]' \
|
||||||
|
- '(uncompress)' \
|
||||||
|
{-d,--decompress}'[decompress]')
|
||||||
|
|
||||||
Normally the option names are taken as multi-character names and a
|
Normally the option names are taken as multi-character names and a
|
||||||
word from the line is considered to contain only one option (or
|
word from the line is considered to contain only one option (or
|
||||||
none). By giving the tt(-s) option to this function (before the first
|
none). By giving the tt(-s) option to this function (before the first
|
||||||
|
@ -2834,6 +2873,11 @@ argument for an option is optional. If it fails to automatically
|
||||||
detect this, the colon before the var(message) can be doubled to tell
|
detect this, the colon before the var(message) can be doubled to tell
|
||||||
it about this as described for the normal option descriptions above.
|
it about this as described for the normal option descriptions above.
|
||||||
|
|
||||||
|
If the var(pattern) ends in `tt((-))', this will removed from the
|
||||||
|
pattern and the var(action) will be used only directly after the
|
||||||
|
`tt(=)', not in the next word. I.e., this is like a normal
|
||||||
|
specification as descrobed above using `tt(=-)'.
|
||||||
|
|
||||||
The option `tt(-i) var(patterns)' (which must be given after the
|
The option `tt(-i) var(patterns)' (which must be given after the
|
||||||
`tt(-)tt(-)') can be used to give patterns for options which should not be
|
`tt(-)tt(-)') can be used to give patterns for options which should not be
|
||||||
completed. The patterns can be given as the name of an array parameter
|
completed. The patterns can be given as the name of an array parameter
|
||||||
|
@ -2875,55 +2919,6 @@ arguments. The first one describes the first argument as a
|
||||||
be completed. The last description says that all other arguments are
|
be completed. The last description says that all other arguments are
|
||||||
`var(page numbers)' but does not give possible completions.
|
`var(page numbers)' but does not give possible completions.
|
||||||
)
|
)
|
||||||
findex(_argument_sets)
|
|
||||||
item(tt(_argument_sets) var(sets) ...)(
|
|
||||||
This is like tt(_arguments) but allows to specify multiple sets of
|
|
||||||
options and arguments. The arguments are sets of specifications for
|
|
||||||
tt(_arguments) separated by single hyphens. The specifications before
|
|
||||||
the first hyphen are shared by all sets given after the first
|
|
||||||
hyphen. The first word in every other set gives the name of the
|
|
||||||
set. This name may appear in exclusion lists in the specifications,
|
|
||||||
either alone or before one of the possible values described for
|
|
||||||
tt(_arguments) above (with a `tt(-)' between the name and the rest).
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
example(_argument_sets \
|
|
||||||
-a \
|
|
||||||
- set1 \
|
|
||||||
-c \
|
|
||||||
- set2 \
|
|
||||||
-d \
|
|
||||||
':arg:(x2 y2)')
|
|
||||||
|
|
||||||
This defines two sets. When the command line contains the option
|
|
||||||
`tt(-c)', the `tt(-d)' option and the argument will not be considered
|
|
||||||
possible completions. When it contains `tt(-d)' or an argument, the
|
|
||||||
option `tt(-c)' will not be completed any more, but if `tt(-a)' is
|
|
||||||
given, both sets will still be considered valid, because it appears
|
|
||||||
before the first hyphen, so both sets contain this option.
|
|
||||||
|
|
||||||
If the name-string is of the form `tt(LPAR())var(name)tt(RPAR())' then
|
|
||||||
all specifications in the set have an implicit exclusion list
|
|
||||||
containing the name of the set, i.e. all specifications are mutual
|
|
||||||
exclusive with all other specifications in the same set. This is
|
|
||||||
useful for defining multiple sets of options which are mutual
|
|
||||||
exclusive and in which the options are aliases for each other. E.g.:
|
|
||||||
|
|
||||||
example(_argument_sets \
|
|
||||||
-a -b \
|
|
||||||
- '(compress)' \
|
|
||||||
{-c,--compress}'[compress]' \
|
|
||||||
- '(uncompress)' \
|
|
||||||
{-d,--decompress}'[decompress]')
|
|
||||||
|
|
||||||
Don't expect too much with complicated options that get their
|
|
||||||
arguments in the same string and `tt(->)var(state)' actions or with
|
|
||||||
the tt(-C) option that is given to tt(_arguments), otherwise most
|
|
||||||
things should work. Note that the contexts reported in the tt(context)
|
|
||||||
array and the options in the tt(opt_args) association are prefixed
|
|
||||||
with the set names and a hyphen.
|
|
||||||
)
|
|
||||||
findex(_call)
|
findex(_call)
|
||||||
item(tt(_call) var(tag) var(string) ...)(
|
item(tt(_call) var(tag) var(string) ...)(
|
||||||
This function is used in places where a command is called and the user
|
This function is used in places where a command is called and the user
|
||||||
|
|
|
@ -293,6 +293,7 @@ typedef struct caarg *Caarg;
|
||||||
|
|
||||||
struct cadef {
|
struct cadef {
|
||||||
Cadef next; /* next in cache */
|
Cadef next; /* next in cache */
|
||||||
|
Cadef snext; /* next set */
|
||||||
Caopt opts; /* the options */
|
Caopt opts; /* the options */
|
||||||
int nopts, ndopts, nodopts; /* number of options/direct/optional direct */
|
int nopts, ndopts, nodopts; /* number of options/direct/optional direct */
|
||||||
Caarg args; /* the normal arguments */
|
Caarg args; /* the normal arguments */
|
||||||
|
@ -304,7 +305,8 @@ struct cadef {
|
||||||
char *match; /* -M spec to use */
|
char *match; /* -M spec to use */
|
||||||
int argsactive; /* if arguments are still allowed */
|
int argsactive; /* if arguments are still allowed */
|
||||||
/* used while parsing a command line */
|
/* used while parsing a command line */
|
||||||
char *set; /* set name, shared */
|
char *set; /* set name prefix (<name>-), shared */
|
||||||
|
char *sname; /* set name */
|
||||||
int flags; /* see CDF_* below */
|
int flags; /* see CDF_* below */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -399,11 +401,14 @@ freecaargs(Caarg a)
|
||||||
static void
|
static void
|
||||||
freecadef(Cadef d)
|
freecadef(Cadef d)
|
||||||
{
|
{
|
||||||
if (d) {
|
Cadef s;
|
||||||
Caopt p, n;
|
Caopt p, n;
|
||||||
|
|
||||||
|
while (d) {
|
||||||
|
s = d->snext;
|
||||||
zsfree(d->match);
|
zsfree(d->match);
|
||||||
zsfree(d->set);
|
zsfree(d->set);
|
||||||
|
zsfree(d->sname);
|
||||||
if (d->defs)
|
if (d->defs)
|
||||||
freearray(d->defs);
|
freearray(d->defs);
|
||||||
|
|
||||||
|
@ -421,6 +426,7 @@ freecadef(Cadef d)
|
||||||
if (d->single)
|
if (d->single)
|
||||||
zfree(d->single, 256 * sizeof(Caopt));
|
zfree(d->single, 256 * sizeof(Caopt));
|
||||||
zfree(d, sizeof(*d));
|
zfree(d, sizeof(*d));
|
||||||
|
d = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,25 +516,63 @@ parse_caarg(int mult, int type, int num, int opt, char *oname, char **def,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Cadef
|
||||||
|
alloc_cadef(char **args, int single, char *match, int flags)
|
||||||
|
{
|
||||||
|
Cadef ret;
|
||||||
|
|
||||||
|
ret = (Cadef) zalloc(sizeof(*ret));
|
||||||
|
ret->next = ret->snext = NULL;
|
||||||
|
ret->opts = NULL;
|
||||||
|
ret->args = ret->rest = NULL;
|
||||||
|
if (args) {
|
||||||
|
ret->defs = zarrdup(args);
|
||||||
|
ret->ndefs = arrlen(args);
|
||||||
|
} else {
|
||||||
|
ret->defs = NULL;
|
||||||
|
ret->ndefs = 0;
|
||||||
|
}
|
||||||
|
ret->lastt = time(0);
|
||||||
|
ret->set = ret->sname = NULL;
|
||||||
|
if (single) {
|
||||||
|
ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
|
||||||
|
memset(ret->single, 0, 256 * sizeof(Caopt));
|
||||||
|
} else
|
||||||
|
ret->single = NULL;
|
||||||
|
ret->match = ztrdup(match);
|
||||||
|
ret->flags = flags;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_cadef_opts(Cadef def)
|
||||||
|
{
|
||||||
|
Caarg argp;
|
||||||
|
int xnum;
|
||||||
|
|
||||||
|
for (argp = def->args, xnum = 0; argp; argp = argp->next) {
|
||||||
|
if (!argp->direct)
|
||||||
|
argp->min = argp->num - xnum;
|
||||||
|
if (argp->type == CAA_OPT)
|
||||||
|
xnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse an array of definitions. */
|
/* Parse an array of definitions. */
|
||||||
|
|
||||||
static Cadef
|
static Cadef
|
||||||
parse_cadef(char *nam, char **args, int multi)
|
parse_cadef(char *nam, char **args)
|
||||||
{
|
{
|
||||||
Cadef ret;
|
Cadef all, ret;
|
||||||
Caopt *optp;
|
Caopt *optp;
|
||||||
Caarg argp;
|
char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs;
|
||||||
char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor;
|
char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL;
|
||||||
char *adpre, *adsuf, *set = NULL, *doset = NULL;
|
|
||||||
int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0;
|
int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0;
|
||||||
|
int state = 0;
|
||||||
|
|
||||||
nopts = ndopts = nodopts = 0;
|
nopts = ndopts = nodopts = 0;
|
||||||
|
|
||||||
if (multi) {
|
|
||||||
if (!args[1])
|
|
||||||
return NULL;
|
|
||||||
set = tricat(*args++, "-", "");
|
|
||||||
}
|
|
||||||
/* First string is the auto-description definition. */
|
/* First string is the auto-description definition. */
|
||||||
|
|
||||||
for (p = args[0]; *p && (p[0] != '%' || p[1] != 'd'); p++);
|
for (p = args[0]; *p && (p[0] != '%' || p[1] != 'd'); p++);
|
||||||
|
@ -582,27 +626,47 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
|
|
||||||
/* Looks good. Optimistically allocate the cadef structure. */
|
/* Looks good. Optimistically allocate the cadef structure. */
|
||||||
|
|
||||||
ret = (Cadef) zalloc(sizeof(*ret));
|
all = ret = alloc_cadef(oargs, single, match, flags);
|
||||||
ret->next = NULL;
|
optp = &(ret->opts);
|
||||||
ret->opts = NULL;
|
single = flags = 0;
|
||||||
ret->args = ret->rest = NULL;
|
anum = 1;
|
||||||
ret->defs = zarrdup(oargs);
|
|
||||||
ret->ndefs = arrlen(oargs);
|
sargs = args;
|
||||||
ret->lastt = time(0);
|
|
||||||
ret->set = set;
|
|
||||||
if (single) {
|
|
||||||
ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
|
|
||||||
memset(ret->single, 0, 256 * sizeof(Caopt));
|
|
||||||
} else
|
|
||||||
ret->single = NULL;
|
|
||||||
ret->match = ztrdup(match);
|
|
||||||
ret->flags = flags;
|
|
||||||
|
|
||||||
/* Get the definitions. */
|
/* Get the definitions. */
|
||||||
|
|
||||||
for (optp = &(ret->opts); *args; args++) {
|
for (; *args; args++) {
|
||||||
if (args[0][0] == '-' && !args[0][1]) {
|
if (args[0][0] == '-' && !args[0][1] && args[1]) {
|
||||||
doset = set;
|
if (!state) {
|
||||||
|
char *p;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
if (setp)
|
||||||
|
args = setp;
|
||||||
|
p = *++args;
|
||||||
|
l = strlen(p) - 1;
|
||||||
|
if (*p == '(' && p[l] == ')') {
|
||||||
|
axor = p = dupstring(p + 1);
|
||||||
|
p[l - 1] = '\0';
|
||||||
|
} else
|
||||||
|
axor = NULL;
|
||||||
|
ret->set = doset = tricat(p, "-", "");
|
||||||
|
ret->sname = ztrdup(p);
|
||||||
|
state = 1;
|
||||||
|
} else {
|
||||||
|
setp = args;
|
||||||
|
state = 0;
|
||||||
|
args = sargs - 1;
|
||||||
|
doset = NULL;
|
||||||
|
ret->nopts = nopts;
|
||||||
|
ret->ndopts = ndopts;
|
||||||
|
ret->nodopts = nodopts;
|
||||||
|
set_cadef_opts(ret);
|
||||||
|
ret = ret->snext = alloc_cadef(NULL, single, NULL, flags);
|
||||||
|
optp = &(ret->opts);
|
||||||
|
single = flags = nopts = ndopts = nodopts = 0;
|
||||||
|
anum = 1;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
p = dupstring(*args);
|
p = dupstring(*args);
|
||||||
|
@ -632,16 +696,25 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
}
|
}
|
||||||
/* Oops, end-of-string. */
|
/* Oops, end-of-string. */
|
||||||
if (*p != ')') {
|
if (*p != ')') {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (doset && axor)
|
||||||
|
xnum++;
|
||||||
xor = (char **) zalloc((xnum + 2) * sizeof(char *));
|
xor = (char **) zalloc((xnum + 2) * sizeof(char *));
|
||||||
for (node = firstnode(list), xp = xor; node; incnode(node), xp++)
|
for (node = firstnode(list), xp = xor; node; incnode(node), xp++)
|
||||||
*xp = ztrdup((char *) getdata(node));
|
*xp = ztrdup((char *) getdata(node));
|
||||||
|
if (doset && axor)
|
||||||
|
*xp++ = ztrdup(axor);
|
||||||
xp[0] = xp[1] = NULL;
|
xp[0] = xp[1] = NULL;
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
|
} else if (doset && axor) {
|
||||||
|
xnum = 1;
|
||||||
|
xor = (char **) zalloc(3 * sizeof(char *));
|
||||||
|
xor[0] = ztrdup(axor);
|
||||||
|
xor[1] = xor[2] = NULL;
|
||||||
} else
|
} else
|
||||||
xor = NULL;
|
xor = NULL;
|
||||||
|
|
||||||
|
@ -676,7 +749,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
if (!p[1]) {
|
if (!p[1]) {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -713,7 +786,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +796,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
descr = NULL;
|
descr = NULL;
|
||||||
|
|
||||||
if (c && c != ':') {
|
if (c && c != ':') {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -766,7 +839,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
*p = sav;
|
*p = sav;
|
||||||
}
|
}
|
||||||
if (*p != ':') {
|
if (*p != ':') {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
freecaargs(oargs);
|
freecaargs(oargs);
|
||||||
zwarnnam(nam, "invalid option definition: %s",
|
zwarnnam(nam, "invalid option definition: %s",
|
||||||
*args, 0);
|
*args, 0);
|
||||||
|
@ -848,12 +921,12 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
int type = CAA_REST;
|
int type = CAA_REST;
|
||||||
|
|
||||||
if (*++p != ':') {
|
if (*++p != ':') {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid rest argument definition: %s", *args, 0);
|
zwarnnam(nam, "invalid rest argument definition: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (ret->rest) {
|
if (ret->rest) {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "doubled rest argument definition: %s", *args, 0);
|
zwarnnam(nam, "doubled rest argument definition: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -885,7 +958,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
anum++;
|
anum++;
|
||||||
|
|
||||||
if (*p != ':') {
|
if (*p != ':') {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -905,7 +978,7 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
pre = tmp, tmp = tmp->next);
|
pre = tmp, tmp = tmp->next);
|
||||||
|
|
||||||
if (tmp && tmp->num == anum - 1) {
|
if (tmp && tmp->num == anum - 1) {
|
||||||
freecadef(ret);
|
freecadef(all);
|
||||||
freecaargs(arg);
|
freecaargs(arg);
|
||||||
zwarnnam(nam, "doubled argument definition: %s", *args, 0);
|
zwarnnam(nam, "doubled argument definition: %s", *args, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -920,21 +993,16 @@ parse_cadef(char *nam, char **args, int multi)
|
||||||
ret->nopts = nopts;
|
ret->nopts = nopts;
|
||||||
ret->ndopts = ndopts;
|
ret->ndopts = ndopts;
|
||||||
ret->nodopts = nodopts;
|
ret->nodopts = nodopts;
|
||||||
|
set_cadef_opts(ret);
|
||||||
|
|
||||||
for (argp = ret->args, xnum = 0; argp; argp = argp->next) {
|
return all;
|
||||||
if (!argp->direct)
|
|
||||||
argp->min = argp->num - xnum;
|
|
||||||
if (argp->type == CAA_OPT)
|
|
||||||
xnum++;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given an array of definitions, return the cadef for it. From the cache
|
/* Given an array of definitions, return the cadef for it. From the cache
|
||||||
* are newly built. */
|
* are newly built. */
|
||||||
|
|
||||||
static Cadef
|
static Cadef
|
||||||
get_cadef(char *nam, char **args, int multi)
|
get_cadef(char *nam, char **args)
|
||||||
{
|
{
|
||||||
Cadef *p, *min, new;
|
Cadef *p, *min, new;
|
||||||
int i, na = arrlen(args);
|
int i, na = arrlen(args);
|
||||||
|
@ -948,7 +1016,7 @@ get_cadef(char *nam, char **args, int multi)
|
||||||
min = p;
|
min = p;
|
||||||
if (i)
|
if (i)
|
||||||
min = p;
|
min = p;
|
||||||
if ((new = parse_cadef(nam, args, multi))) {
|
if ((new = parse_cadef(nam, args))) {
|
||||||
freecadef(*min);
|
freecadef(*min);
|
||||||
*min = new;
|
*min = new;
|
||||||
}
|
}
|
||||||
|
@ -1120,7 +1188,10 @@ ca_inactive(Cadef d, char **xor, int cur, int opts)
|
||||||
|
|
||||||
/* State when parsing a command line. */
|
/* State when parsing a command line. */
|
||||||
|
|
||||||
|
typedef struct castate *Castate;
|
||||||
|
|
||||||
struct castate {
|
struct castate {
|
||||||
|
Castate snext;
|
||||||
Cadef d;
|
Cadef d;
|
||||||
int nopts;
|
int nopts;
|
||||||
Caarg def, ddef;
|
Caarg def, ddef;
|
||||||
|
@ -1134,10 +1205,23 @@ struct castate {
|
||||||
static struct castate ca_laststate;
|
static struct castate ca_laststate;
|
||||||
static int ca_parsed = 0, ca_alloced = 0;
|
static int ca_parsed = 0, ca_alloced = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
freecastate(Castate s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LinkList *p;
|
||||||
|
|
||||||
|
freelinklist(s->args, freestr);
|
||||||
|
for (i = s->nopts, p = s->oargs; i--; p++)
|
||||||
|
if (*p)
|
||||||
|
freelinklist(*p, freestr);
|
||||||
|
zfree(s->oargs, s->d->nopts * sizeof(LinkList));
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse a command line. */
|
/* Parse a command line. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ca_parse_line(Cadef d, int multi)
|
ca_parse_line(Cadef d, int multi, int first)
|
||||||
{
|
{
|
||||||
Caarg adef, ddef;
|
Caarg adef, ddef;
|
||||||
Caopt ptr, wasopt, dopt;
|
Caopt ptr, wasopt, dopt;
|
||||||
|
@ -1148,16 +1232,17 @@ ca_parse_line(Cadef d, int multi)
|
||||||
|
|
||||||
/* Free old state. */
|
/* Free old state. */
|
||||||
|
|
||||||
if (ca_alloced) {
|
if (first && ca_alloced) {
|
||||||
int i = ca_laststate.nopts;
|
Castate s = &ca_laststate, ss;
|
||||||
LinkList *p = ca_laststate.oargs;
|
int f = 1;
|
||||||
|
|
||||||
freelinklist(ca_laststate.args, freestr);
|
while (s) {
|
||||||
while (i--)
|
ss = s->snext;
|
||||||
if (*p++)
|
freecastate(s);
|
||||||
freelinklist(p[-1], freestr);
|
if (!f)
|
||||||
|
zfree(s, sizeof(*s));
|
||||||
zfree(ca_laststate.oargs, ca_laststate.d->nopts * sizeof(LinkList));
|
s = ss;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Mark everything as active. */
|
/* Mark everything as active. */
|
||||||
|
|
||||||
|
@ -1171,6 +1256,7 @@ ca_parse_line(Cadef d, int multi)
|
||||||
|
|
||||||
/* Default values for the state. */
|
/* Default values for the state. */
|
||||||
|
|
||||||
|
state.snext = NULL;
|
||||||
state.d = d;
|
state.d = d;
|
||||||
state.nopts = d->nopts;
|
state.nopts = d->nopts;
|
||||||
state.def = state.ddef = NULL;
|
state.def = state.ddef = NULL;
|
||||||
|
@ -1482,16 +1568,13 @@ ca_colonlist(LinkList l)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ca_set_data(char *opt, Caarg arg, char **args, int single)
|
ca_set_data(LinkList descr, LinkList act, LinkList subc,
|
||||||
|
char *opt, Caarg arg, int single)
|
||||||
{
|
{
|
||||||
LinkList descr, act, subc;
|
LinkNode dnode, anode;
|
||||||
char nbuf[40], *buf;
|
char nbuf[40], *buf;
|
||||||
int restr = 0, onum, miss = 0, rest, oopt = 1, lopt = 0, addopt;
|
int restr = 0, onum, miss = 0, rest, oopt = 1, lopt = 0, addopt;
|
||||||
|
|
||||||
descr = newlinklist();
|
|
||||||
act = newlinklist();
|
|
||||||
subc = newlinklist();
|
|
||||||
|
|
||||||
rec:
|
rec:
|
||||||
|
|
||||||
addopt = (opt ? 0 : ca_laststate.oopt);
|
addopt = (opt ? 0 : ca_laststate.oopt);
|
||||||
|
@ -1503,33 +1586,40 @@ ca_set_data(char *opt, Caarg arg, char **args, int single)
|
||||||
if (!opt && !lopt && oopt > 0)
|
if (!opt && !lopt && oopt > 0)
|
||||||
oopt = 0;
|
oopt = 0;
|
||||||
|
|
||||||
addlinknode(descr, arg->descr);
|
for (dnode = firstnode(descr), anode = firstnode(act);
|
||||||
addlinknode(act, arg->action);
|
dnode; incnode(dnode), incnode(anode))
|
||||||
|
if (!strcmp((char *) getdata(dnode), arg->descr) &&
|
||||||
|
!strcmp((char *) getdata(anode), arg->action))
|
||||||
|
break;
|
||||||
|
|
||||||
if (!restr) {
|
if (!dnode) {
|
||||||
if ((restr = (arg->type == CAA_RARGS)))
|
addlinknode(descr, arg->descr);
|
||||||
restrict_range(ca_laststate.optbeg, ca_laststate.argend);
|
addlinknode(act, arg->action);
|
||||||
else if ((restr = (arg->type == CAA_RREST)))
|
|
||||||
restrict_range(ca_laststate.argbeg, ca_laststate.argend);
|
if (!restr) {
|
||||||
|
if ((restr = (arg->type == CAA_RARGS)))
|
||||||
|
restrict_range(ca_laststate.optbeg, ca_laststate.argend);
|
||||||
|
else if ((restr = (arg->type == CAA_RREST)))
|
||||||
|
restrict_range(ca_laststate.argbeg, ca_laststate.argend);
|
||||||
|
}
|
||||||
|
if (arg->opt) {
|
||||||
|
buf = (char *) zhalloc((arg->set ? strlen(arg->set) : 0) +
|
||||||
|
strlen(arg->opt) + 40);
|
||||||
|
if (arg->num > 0 && arg->type < CAA_REST)
|
||||||
|
sprintf(buf, "%soption%s-%d",
|
||||||
|
(arg->set ? arg->set : ""), arg->opt, arg->num);
|
||||||
|
else
|
||||||
|
sprintf(buf, "%soption%s-rest",
|
||||||
|
(arg->set ? arg->set : ""), arg->opt);
|
||||||
|
} else if (arg->num > 0) {
|
||||||
|
sprintf(nbuf, "argument-%d", arg->num);
|
||||||
|
buf = (arg->set ? dyncat(arg->set, nbuf) : dupstring(nbuf));
|
||||||
|
} else
|
||||||
|
buf = (arg->set ? dyncat(arg->set, "argument-rest") :
|
||||||
|
dupstring("argument-rest"));
|
||||||
|
|
||||||
|
addlinknode(subc, buf);
|
||||||
}
|
}
|
||||||
if (arg->opt) {
|
|
||||||
buf = (char *) zhalloc((arg->set ? strlen(arg->set) : 0) +
|
|
||||||
strlen(arg->opt) + 40);
|
|
||||||
if (arg->num > 0 && arg->type < CAA_REST)
|
|
||||||
sprintf(buf, "%soption%s-%d",
|
|
||||||
(arg->set ? arg->set : ""), arg->opt, arg->num);
|
|
||||||
else
|
|
||||||
sprintf(buf, "%soption%s-rest",
|
|
||||||
(arg->set ? arg->set : ""), arg->opt);
|
|
||||||
} else if (arg->num > 0) {
|
|
||||||
sprintf(nbuf, "argument-%d", arg->num);
|
|
||||||
buf = (arg->set ? dyncat(arg->set, nbuf) : dupstring(nbuf));
|
|
||||||
} else
|
|
||||||
buf = (arg->set ? dyncat(arg->set, "argument-rest") :
|
|
||||||
dupstring("argument-rest"));
|
|
||||||
|
|
||||||
addlinknode(subc, buf);
|
|
||||||
|
|
||||||
if (single)
|
if (single)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1565,15 +1655,13 @@ ca_set_data(char *opt, Caarg arg, char **args, int single)
|
||||||
|
|
||||||
goto rec;
|
goto rec;
|
||||||
}
|
}
|
||||||
set_list_array(args[0], descr);
|
|
||||||
set_list_array(args[1], act);
|
|
||||||
set_list_array(args[2], subc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bin_comparguments(char *nam, char **args, char *ops, int func)
|
bin_comparguments(char *nam, char **args, char *ops, int func)
|
||||||
{
|
{
|
||||||
int min, max, n;
|
int min, max, n;
|
||||||
|
Castate lstate = &ca_laststate;
|
||||||
|
|
||||||
if (incompfunc != 1) {
|
if (incompfunc != 1) {
|
||||||
zwarnnam(nam, "can only be called from completion function", NULL, 0);
|
zwarnnam(nam, "can only be called from completion function", NULL, 0);
|
||||||
|
@ -1588,8 +1676,7 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
switch (args[0][1]) {
|
switch (args[0][1]) {
|
||||||
case 'i':
|
case 'i': min = 2; max = -1; break;
|
||||||
case 'I': min = 2; max = -1; break;
|
|
||||||
case 'D': min = 3; max = 3; break;
|
case 'D': min = 3; max = 3; break;
|
||||||
case 'O': min = 4; max = 4; break;
|
case 'O': min = 4; max = 4; break;
|
||||||
case 'L': min = 3; max = 4; break;
|
case 'L': min = 3; max = 4; break;
|
||||||
|
@ -1611,171 +1698,235 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
|
||||||
}
|
}
|
||||||
switch (args[0][1]) {
|
switch (args[0][1]) {
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'I':
|
|
||||||
if (compcurrent > 1 && compwords[0]) {
|
if (compcurrent > 1 && compwords[0]) {
|
||||||
Cadef def;
|
Cadef def;
|
||||||
int cap = ca_parsed;
|
int cap = ca_parsed, multi, first = 1, use, ret = 0;
|
||||||
LinkList cax = ca_xor;
|
LinkList cax = ca_xor, nx;
|
||||||
|
LinkNode node;
|
||||||
|
Castate states = NULL, sp;
|
||||||
|
char *xor[2];
|
||||||
|
|
||||||
ca_parsed = 0;
|
ca_parsed = 0;
|
||||||
|
xor[1] = NULL;
|
||||||
|
|
||||||
if (args[0][1] == 'I') {
|
if (!(def = get_cadef(nam, args + 1)))
|
||||||
char **xor;
|
return 1;
|
||||||
|
|
||||||
if (!(def = get_cadef(nam, args + 2, 1)))
|
multi = !!def->snext;
|
||||||
return 1;
|
ca_parsed = cap;
|
||||||
|
ca_xor = (multi ? newlinklist() : NULL);
|
||||||
|
|
||||||
ca_parsed = cap;
|
while (def) {
|
||||||
ca_xor = newlinklist();
|
use = !ca_parse_line(def, multi, first);
|
||||||
if ((xor = getaparam(args[1]))) {
|
nx = ca_xor;
|
||||||
if (arrcontains(xor, args[2], 0) ||
|
ca_xor = NULL;
|
||||||
ca_inactive(def, xor, compcurrent, 0)) {
|
while ((def = def->snext)) {
|
||||||
ca_xor = cax;
|
if (nx) {
|
||||||
return 1;
|
for (node = firstnode(nx); node; incnode(node)) {
|
||||||
|
xor[0] = (char *) getdata(node);
|
||||||
|
if (!strcmp(xor[0], def->sname) ||
|
||||||
|
ca_inactive(def, xor, compcurrent, 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!node)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ca_parse_line(def, 1)) {
|
ca_xor = nx;
|
||||||
ca_xor = cax;
|
if (use && def) {
|
||||||
return 1;
|
sp = (Castate) zalloc(sizeof(*sp));
|
||||||
|
memcpy(sp, &ca_laststate, sizeof(*sp));
|
||||||
|
sp->snext = states;
|
||||||
|
states = sp;
|
||||||
|
} else if (!use && !def) {
|
||||||
|
if (states) {
|
||||||
|
freecastate(&ca_laststate);
|
||||||
|
memcpy(&ca_laststate, states, sizeof(*sp));
|
||||||
|
sp = states->snext;
|
||||||
|
zfree(states, sizeof(*states));
|
||||||
|
states = sp;
|
||||||
|
} else
|
||||||
|
ret = 1;
|
||||||
}
|
}
|
||||||
set_list_array(args[1], ca_xor);
|
first = 0;
|
||||||
} else {
|
|
||||||
if (!(def = get_cadef(nam, args + 1, 0)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
ca_parsed = cap;
|
|
||||||
ca_xor = NULL;
|
|
||||||
ca_parse_line(def, 0);
|
|
||||||
}
|
}
|
||||||
ca_xor = cax;
|
ca_xor = cax;
|
||||||
ca_parsed = 1;
|
ca_parsed = 1;
|
||||||
|
ca_laststate.snext = states;
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
{
|
{
|
||||||
Caarg arg = ca_laststate.def;
|
LinkList descr, act, subc;
|
||||||
|
Caarg arg;
|
||||||
|
int ign = 0, ret = 1;
|
||||||
|
|
||||||
if (arg) {
|
descr = newlinklist();
|
||||||
if (ca_laststate.doff > 0)
|
act = newlinklist();
|
||||||
ignore_prefix(ca_laststate.doff);
|
subc = newlinklist();
|
||||||
|
|
||||||
ca_set_data(arg->opt, arg, args + 1, (ca_laststate.doff > 0));
|
while (lstate) {
|
||||||
|
arg = lstate->def;
|
||||||
|
|
||||||
return 0;
|
if (arg) {
|
||||||
|
ret = 0;
|
||||||
|
if (!ign && lstate->doff > 0) {
|
||||||
|
ign = 1;
|
||||||
|
ignore_prefix(lstate->doff);
|
||||||
|
}
|
||||||
|
ca_set_data(descr, act, subc, arg->opt, arg,
|
||||||
|
(lstate->doff > 0));
|
||||||
|
}
|
||||||
|
lstate = lstate->snext;
|
||||||
}
|
}
|
||||||
return 1;
|
if (!ret) {
|
||||||
|
set_list_array(args[1], descr);
|
||||||
|
set_list_array(args[2], act);
|
||||||
|
set_list_array(args[3], subc);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
case 'O':
|
case 'O':
|
||||||
if (ca_laststate.actopts &&
|
{
|
||||||
(ca_laststate.opt || (ca_laststate.doff && ca_laststate.def) ||
|
|
||||||
(ca_laststate.def &&
|
|
||||||
(ca_laststate.def->type == CAA_OPT ||
|
|
||||||
(ca_laststate.def->type >= CAA_RARGS &&
|
|
||||||
ca_laststate.def->num < 0)))) &&
|
|
||||||
(!ca_laststate.def || ca_laststate.def->type < CAA_RARGS ||
|
|
||||||
(ca_laststate.def->type == CAA_RARGS ?
|
|
||||||
(ca_laststate.curpos == ca_laststate.argbeg + 1) :
|
|
||||||
(compcurrent == 1)))) {
|
|
||||||
LinkList next = newlinklist();
|
LinkList next = newlinklist();
|
||||||
LinkList direct = newlinklist();
|
LinkList direct = newlinklist();
|
||||||
LinkList odirect = newlinklist();
|
LinkList odirect = newlinklist();
|
||||||
LinkList equal = newlinklist(), l;
|
LinkList equal = newlinklist(), l;
|
||||||
Caopt p;
|
Caopt p;
|
||||||
char *str;
|
char *str;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
for (p = ca_laststate.d->opts; p; p = p->next) {
|
for (; lstate; lstate = lstate->snext) {
|
||||||
if (p->active) {
|
if (lstate->actopts &&
|
||||||
switch (p->type) {
|
(lstate->opt || (lstate->doff && lstate->def) ||
|
||||||
case CAO_NEXT: l = next; break;
|
(lstate->def &&
|
||||||
case CAO_DIRECT: l = direct; break;
|
(lstate->def->type == CAA_OPT ||
|
||||||
case CAO_ODIRECT: l = odirect; break;
|
(lstate->def->type >= CAA_RARGS &&
|
||||||
default: l = equal; break;
|
lstate->def->num < 0)))) &&
|
||||||
|
(!lstate->def || lstate->def->type < CAA_RARGS ||
|
||||||
|
(lstate->def->type == CAA_RARGS ?
|
||||||
|
(lstate->curpos == lstate->argbeg + 1) :
|
||||||
|
(compcurrent == 1)))) {
|
||||||
|
ret = 0;
|
||||||
|
for (p = lstate->d->opts; p; p = p->next) {
|
||||||
|
if (p->active) {
|
||||||
|
switch (p->type) {
|
||||||
|
case CAO_NEXT: l = next; break;
|
||||||
|
case CAO_DIRECT: l = direct; break;
|
||||||
|
case CAO_ODIRECT: l = odirect; break;
|
||||||
|
default: l = equal; break;
|
||||||
|
}
|
||||||
|
if (p->descr) {
|
||||||
|
char *n = bslashcolon(p->name);
|
||||||
|
int len = strlen(n) + strlen(p->descr) + 2;
|
||||||
|
|
||||||
|
str = (char *) zhalloc(len);
|
||||||
|
strcpy(str, n);
|
||||||
|
strcat(str, ":");
|
||||||
|
strcat(str, p->descr);
|
||||||
|
} else
|
||||||
|
str = bslashcolon(p->name);
|
||||||
|
addlinknode(l, str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p->descr) {
|
|
||||||
char *n = bslashcolon(p->name);
|
|
||||||
int len = strlen(n) + strlen(p->descr) + 2;
|
|
||||||
|
|
||||||
str = (char *) zhalloc(len);
|
|
||||||
strcpy(str, n);
|
|
||||||
strcat(str, ":");
|
|
||||||
strcat(str, p->descr);
|
|
||||||
} else
|
|
||||||
str = bslashcolon(p->name);
|
|
||||||
addlinknode(l, str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_list_array(args[1], next);
|
if (!ret) {
|
||||||
set_list_array(args[2], direct);
|
set_list_array(args[1], next);
|
||||||
set_list_array(args[3], odirect);
|
set_list_array(args[2], direct);
|
||||||
set_list_array(args[4], equal);
|
set_list_array(args[3], odirect);
|
||||||
|
set_list_array(args[4], equal);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (ca_laststate.singles ? 2 : 1);
|
|
||||||
case 'L':
|
|
||||||
{
|
|
||||||
Caopt opt = ca_get_opt(ca_laststate.d, args[1], 1, NULL);
|
|
||||||
|
|
||||||
if (opt && opt->args) {
|
|
||||||
ca_set_data(opt->name, opt->args, args + 2, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return (ca_laststate.singles ? 2 : 1);
|
||||||
|
}
|
||||||
|
case 'L':
|
||||||
|
{
|
||||||
|
LinkList descr, act, subc;
|
||||||
|
Caopt opt;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
descr = newlinklist();
|
||||||
|
act = newlinklist();
|
||||||
|
subc = newlinklist();
|
||||||
|
|
||||||
|
while (lstate) {
|
||||||
|
opt = ca_get_opt(lstate->d, args[1], 1, NULL);
|
||||||
|
|
||||||
|
if (opt && opt->args) {
|
||||||
|
ret = 0;
|
||||||
|
ca_set_data(descr, act, subc, opt->name, opt->args, 1);
|
||||||
|
}
|
||||||
|
lstate = lstate->snext;
|
||||||
|
}
|
||||||
|
if (!ret) {
|
||||||
|
set_list_array(args[2], descr);
|
||||||
|
set_list_array(args[3], act);
|
||||||
|
set_list_array(args[4], subc);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
case 's':
|
case 's':
|
||||||
if (ca_laststate.d->single && ca_laststate.singles &&
|
for (; lstate; lstate = lstate->snext)
|
||||||
ca_laststate.actopts && ca_laststate.opt) {
|
if (lstate->d->single && lstate->singles &&
|
||||||
setsparam(args[1],
|
lstate->actopts && lstate->opt) {
|
||||||
ztrdup((ca_laststate.ddef && ca_laststate.dopt) ?
|
setsparam(args[1],
|
||||||
(ca_laststate.dopt->type == CAO_DIRECT ?
|
ztrdup((lstate->ddef && lstate->dopt) ?
|
||||||
"direct" :
|
(lstate->dopt->type == CAO_DIRECT ?
|
||||||
((ca_laststate.dopt->type == CAO_OEQUAL ||
|
"direct" :
|
||||||
ca_laststate.dopt->type == CAO_EQUAL) ?
|
((lstate->dopt->type == CAO_OEQUAL ||
|
||||||
"equal" : "next")) : ""));
|
lstate->dopt->type == CAO_EQUAL) ?
|
||||||
return 0;
|
"equal" : "next")) : ""));
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
case 'M':
|
case 'M':
|
||||||
setsparam(args[1], ztrdup(ca_laststate.d->match));
|
setsparam(args[1], ztrdup(ca_laststate.d->match));
|
||||||
return 0;
|
return 0;
|
||||||
case 'a':
|
case 'a':
|
||||||
return !(ca_laststate.d->args || ca_laststate.d->rest);
|
for (; lstate; lstate = lstate->snext)
|
||||||
|
if (lstate->d->args || lstate->d->rest)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
case 'W':
|
case 'W':
|
||||||
{
|
{
|
||||||
|
Castate s;
|
||||||
char **ret, **p;
|
char **ret, **p;
|
||||||
LinkNode n;
|
LinkNode n;
|
||||||
LinkList *a;
|
LinkList *a;
|
||||||
Caopt o;
|
Caopt o;
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
ret = p = zalloc((countlinknodes(ca_laststate.args) + 1) *
|
for (num = 0, s = lstate; s; s = s->snext)
|
||||||
sizeof(char *));
|
num += countlinknodes(s->args);
|
||||||
|
|
||||||
for (n = firstnode(ca_laststate.args); n; incnode(n))
|
ret = p = zalloc((num + 1) * sizeof(char *));
|
||||||
*p++ = ztrdup((char *) getdata(n));
|
|
||||||
|
for (s = lstate; s; s = s->snext)
|
||||||
|
for (n = firstnode(s->args); n; incnode(n))
|
||||||
|
*p++ = ztrdup((char *) getdata(n));
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
|
|
||||||
setaparam(args[1], ret);
|
setaparam(args[1], ret);
|
||||||
|
|
||||||
for (num = 0, o = ca_laststate.d->opts, a = ca_laststate.oargs; o;
|
for (num = 0, s = lstate; s; s = s->snext)
|
||||||
o = o->next, a++)
|
for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
|
||||||
if (*a)
|
if (*a)
|
||||||
num += 2;
|
num += 2;
|
||||||
|
|
||||||
ret = p = zalloc((num + 1) * sizeof(char *));
|
ret = p = zalloc((num + 1) * sizeof(char *));
|
||||||
|
|
||||||
for (o = ca_laststate.d->opts, a = ca_laststate.oargs; o;
|
for (s = lstate; s; s = s->snext)
|
||||||
o = o->next, a++) {
|
for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
|
||||||
if (*a) {
|
if (*a) {
|
||||||
*p++ = (o->set ? tricat(o->set, o->name, "") :
|
*p++ = (o->set ? tricat(o->set, o->name, "") :
|
||||||
ztrdup(o->name));
|
ztrdup(o->name));
|
||||||
*p++ = ca_colonlist(*a);
|
*p++ = ca_colonlist(*a);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
|
|
||||||
sethparam(args[2], ret);
|
sethparam(args[2], ret);
|
||||||
|
|
Loading…
Reference in a new issue