mirror of
https://github.com/zsh-users/zsh
synced 2024-10-07 16:39:09 +00: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
|
@ -1,5 +1,10 @@
|
|||
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
|
||||
a-a-m-c in menu selection; scroll explanations onto screen again
|
||||
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.
|
||||
|
||||
local long cmd="$words[1]" descr mesg subopts opt usecc autod
|
||||
local oldcontext="$curcontext" hasopts multi ismulti
|
||||
local oldcontext="$curcontext" hasopts
|
||||
|
||||
long=$argv[(I)--]
|
||||
if (( long )); then
|
||||
|
@ -23,7 +23,7 @@ if (( long )); then
|
|||
name="${name//[^a-zA-Z0-9_]/_}"
|
||||
|
||||
if (( ! ${(P)+name} )); then
|
||||
local iopts sopts pattern tmpo cur cache
|
||||
local iopts sopts pattern tmpo dir cur cache
|
||||
typeset -U lopts
|
||||
|
||||
cache=()
|
||||
|
@ -98,6 +98,12 @@ if (( long )); then
|
|||
|
||||
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
|
||||
|
@ -111,7 +117,7 @@ if (( long )); then
|
|||
|
||||
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.
|
||||
|
||||
tmpo=("${(@M)tmp:#*\[\=*}")
|
||||
|
@ -120,9 +126,9 @@ if (( long )); then
|
|||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||
|
||||
if [[ "$descr" = ::* ]]; then
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||
else
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=:${descr}" )
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}:${descr}" )
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -133,10 +139,10 @@ if (( long )); then
|
|||
tmp=("${(@)tmp:#*\=*}")
|
||||
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
|
||||
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
|
||||
cache=( "$cache[@]" "${(@)^tmpo}=${dir}${descr}" )
|
||||
fi
|
||||
|
||||
# Everything else is just added as a option without arguments.
|
||||
# Everything else is just added as an option without arguments.
|
||||
|
||||
if (( $#tmp )); then
|
||||
tmp=("${(@)tmp//[^a-zA-Z0-9-]}")
|
||||
|
@ -148,27 +154,22 @@ if (( long )); then
|
|||
set -- "$tmpargv[@]" "${(@P)name}"
|
||||
fi
|
||||
|
||||
multi=(-i)
|
||||
subopts=()
|
||||
while [[ "$1" = -(O*|C|m*) ]]; do
|
||||
case "$1" in
|
||||
-C) usecc=yes; shift ;;
|
||||
-O) subopts=( "${(@P)2}" ); shift 2 ;;
|
||||
-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
|
||||
done
|
||||
|
||||
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 next direct odirect equal single matcher matched ws tmp1 tmp2 tmp3
|
||||
local opts subc tc prefix suffix descrs actions subcs
|
||||
local origpre="$PREFIX" origipre="$IPREFIX"
|
||||
|
||||
[[ -z "$ismulti" ]] && local nm="$compstate[nmatches]"
|
||||
local origpre="$PREFIX" origipre="$IPREFIX" nm="$compstate[nmatches]"
|
||||
|
||||
if comparguments -D descrs actions subcs; then
|
||||
if comparguments -O next direct odirect equal; then
|
||||
|
@ -180,7 +181,6 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
|||
else
|
||||
if comparguments -a; then
|
||||
noargs='no more arguments'
|
||||
had_args=yes
|
||||
else
|
||||
noargs='no arguments'
|
||||
fi
|
||||
|
@ -299,8 +299,7 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
|||
done
|
||||
|
||||
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
|
||||
local prevpre="$PREFIX" previpre="$IPREFIX"
|
||||
|
||||
|
@ -326,37 +325,22 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
|||
tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
|
||||
tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
|
||||
|
||||
if [[ -n "$ismulti" ]]; then
|
||||
_ms_opt=yes
|
||||
_ms_soptmid=( "$_ms_soptmid[@]" "$tmp1[@]" )
|
||||
_ms_soptmidadd=( "$_ms_soptmidadd[@]" "$tmp2[@]" )
|
||||
_ms_soptend=( "$_ms_soptend[@]" "$tmp3[@]" )
|
||||
else
|
||||
_describe -o option \
|
||||
tmp1 tmp2 -Q -S '' -- \
|
||||
tmp3 -Q
|
||||
fi
|
||||
_describe -o option \
|
||||
tmp1 tmp2 -Q -S '' -- \
|
||||
tmp3 -Q
|
||||
fi
|
||||
single=yes
|
||||
else
|
||||
next=( "$next[@]" "$odirect[@]" )
|
||||
if [[ -n "$ismulti" ]]; then
|
||||
_ms_opt=yes
|
||||
_ms_match="$_ms_match $matcher"
|
||||
_ms_optnext=( "$_ms_optnext[@]" "$next[@]" )
|
||||
_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
|
||||
_describe -o option \
|
||||
next -Q -M "$matcher" -- \
|
||||
direct -QS '' -M "$matcher" -- \
|
||||
equal -QqS= -M "$matcher"
|
||||
fi
|
||||
PREFIX="$prevpre"
|
||||
IPREFIX="$previpre"
|
||||
fi
|
||||
[[ -n "$tried" ]] && break
|
||||
[[ -n "$tried" && "$PREFIX" != [-+]* ]] && break
|
||||
done
|
||||
if [[ -n "$opts" && -z "$aret$matched$mesg" &&
|
||||
nm -eq compstate[nmatches] ]]; then
|
||||
|
@ -391,11 +375,7 @@ if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
|
|||
|
||||
[[ -n "$aret" ]] && return 300
|
||||
|
||||
if [[ -n "$noargs" ]]; then
|
||||
[[ -z "$ismulti" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
|
||||
else
|
||||
has_args=yes
|
||||
fi
|
||||
[[ -n "$noargs" && nm -eq "$compstate[nmatches]" ]] && _message "$noargs"
|
||||
|
||||
# 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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
`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
|
||||
|
@ -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
|
||||
`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)
|
||||
item(tt(_call) var(tag) var(string) ...)(
|
||||
This function is used in places where a command is called and the user
|
||||
|
|
|
@ -293,6 +293,7 @@ typedef struct caarg *Caarg;
|
|||
|
||||
struct cadef {
|
||||
Cadef next; /* next in cache */
|
||||
Cadef snext; /* next set */
|
||||
Caopt opts; /* the options */
|
||||
int nopts, ndopts, nodopts; /* number of options/direct/optional direct */
|
||||
Caarg args; /* the normal arguments */
|
||||
|
@ -304,7 +305,8 @@ struct cadef {
|
|||
char *match; /* -M spec to use */
|
||||
int argsactive; /* if arguments are still allowed */
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
|
@ -399,11 +401,14 @@ freecaargs(Caarg a)
|
|||
static void
|
||||
freecadef(Cadef d)
|
||||
{
|
||||
if (d) {
|
||||
Caopt p, n;
|
||||
Cadef s;
|
||||
Caopt p, n;
|
||||
|
||||
while (d) {
|
||||
s = d->snext;
|
||||
zsfree(d->match);
|
||||
zsfree(d->set);
|
||||
zsfree(d->sname);
|
||||
if (d->defs)
|
||||
freearray(d->defs);
|
||||
|
||||
|
@ -421,6 +426,7 @@ freecadef(Cadef d)
|
|||
if (d->single)
|
||||
zfree(d->single, 256 * sizeof(Caopt));
|
||||
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;
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
static Cadef
|
||||
parse_cadef(char *nam, char **args, int multi)
|
||||
parse_cadef(char *nam, char **args)
|
||||
{
|
||||
Cadef ret;
|
||||
Cadef all, ret;
|
||||
Caopt *optp;
|
||||
Caarg argp;
|
||||
char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor;
|
||||
char *adpre, *adsuf, *set = NULL, *doset = NULL;
|
||||
char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs;
|
||||
char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL;
|
||||
int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0;
|
||||
int state = 0;
|
||||
|
||||
nopts = ndopts = nodopts = 0;
|
||||
|
||||
if (multi) {
|
||||
if (!args[1])
|
||||
return NULL;
|
||||
set = tricat(*args++, "-", "");
|
||||
}
|
||||
/* First string is the auto-description definition. */
|
||||
|
||||
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. */
|
||||
|
||||
ret = (Cadef) zalloc(sizeof(*ret));
|
||||
ret->next = NULL;
|
||||
ret->opts = NULL;
|
||||
ret->args = ret->rest = NULL;
|
||||
ret->defs = zarrdup(oargs);
|
||||
ret->ndefs = arrlen(oargs);
|
||||
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;
|
||||
all = ret = alloc_cadef(oargs, single, match, flags);
|
||||
optp = &(ret->opts);
|
||||
single = flags = 0;
|
||||
anum = 1;
|
||||
|
||||
sargs = args;
|
||||
|
||||
/* Get the definitions. */
|
||||
|
||||
for (optp = &(ret->opts); *args; args++) {
|
||||
if (args[0][0] == '-' && !args[0][1]) {
|
||||
doset = set;
|
||||
for (; *args; args++) {
|
||||
if (args[0][0] == '-' && !args[0][1] && args[1]) {
|
||||
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;
|
||||
}
|
||||
p = dupstring(*args);
|
||||
|
@ -632,16 +696,25 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
}
|
||||
/* Oops, end-of-string. */
|
||||
if (*p != ')') {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (doset && axor)
|
||||
xnum++;
|
||||
xor = (char **) zalloc((xnum + 2) * sizeof(char *));
|
||||
for (node = firstnode(list), xp = xor; node; incnode(node), xp++)
|
||||
*xp = ztrdup((char *) getdata(node));
|
||||
if (doset && axor)
|
||||
*xp++ = ztrdup(axor);
|
||||
xp[0] = xp[1] = NULL;
|
||||
|
||||
p++;
|
||||
} else if (doset && axor) {
|
||||
xnum = 1;
|
||||
xor = (char **) zalloc(3 * sizeof(char *));
|
||||
xor[0] = ztrdup(axor);
|
||||
xor[1] = xor[2] = NULL;
|
||||
} else
|
||||
xor = NULL;
|
||||
|
||||
|
@ -676,7 +749,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
p++;
|
||||
}
|
||||
if (!p[1]) {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -713,7 +786,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
p++;
|
||||
|
||||
if (!*p) {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -723,7 +796,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
descr = NULL;
|
||||
|
||||
if (c && c != ':') {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid option definition: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -766,7 +839,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
*p = sav;
|
||||
}
|
||||
if (*p != ':') {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
freecaargs(oargs);
|
||||
zwarnnam(nam, "invalid option definition: %s",
|
||||
*args, 0);
|
||||
|
@ -848,12 +921,12 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
int type = CAA_REST;
|
||||
|
||||
if (*++p != ':') {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid rest argument definition: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (ret->rest) {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "doubled rest argument definition: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -885,7 +958,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
anum++;
|
||||
|
||||
if (*p != ':') {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
zwarnnam(nam, "invalid argument: %s", *args, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -905,7 +978,7 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
pre = tmp, tmp = tmp->next);
|
||||
|
||||
if (tmp && tmp->num == anum - 1) {
|
||||
freecadef(ret);
|
||||
freecadef(all);
|
||||
freecaargs(arg);
|
||||
zwarnnam(nam, "doubled argument definition: %s", *args, 0);
|
||||
return NULL;
|
||||
|
@ -920,21 +993,16 @@ parse_cadef(char *nam, char **args, int multi)
|
|||
ret->nopts = nopts;
|
||||
ret->ndopts = ndopts;
|
||||
ret->nodopts = nodopts;
|
||||
set_cadef_opts(ret);
|
||||
|
||||
for (argp = ret->args, xnum = 0; argp; argp = argp->next) {
|
||||
if (!argp->direct)
|
||||
argp->min = argp->num - xnum;
|
||||
if (argp->type == CAA_OPT)
|
||||
xnum++;
|
||||
}
|
||||
return ret;
|
||||
return all;
|
||||
}
|
||||
|
||||
/* Given an array of definitions, return the cadef for it. From the cache
|
||||
* are newly built. */
|
||||
|
||||
static Cadef
|
||||
get_cadef(char *nam, char **args, int multi)
|
||||
get_cadef(char *nam, char **args)
|
||||
{
|
||||
Cadef *p, *min, new;
|
||||
int i, na = arrlen(args);
|
||||
|
@ -948,7 +1016,7 @@ get_cadef(char *nam, char **args, int multi)
|
|||
min = p;
|
||||
if (i)
|
||||
min = p;
|
||||
if ((new = parse_cadef(nam, args, multi))) {
|
||||
if ((new = parse_cadef(nam, args))) {
|
||||
freecadef(*min);
|
||||
*min = new;
|
||||
}
|
||||
|
@ -1120,7 +1188,10 @@ ca_inactive(Cadef d, char **xor, int cur, int opts)
|
|||
|
||||
/* State when parsing a command line. */
|
||||
|
||||
typedef struct castate *Castate;
|
||||
|
||||
struct castate {
|
||||
Castate snext;
|
||||
Cadef d;
|
||||
int nopts;
|
||||
Caarg def, ddef;
|
||||
|
@ -1134,10 +1205,23 @@ struct castate {
|
|||
static struct castate ca_laststate;
|
||||
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. */
|
||||
|
||||
static int
|
||||
ca_parse_line(Cadef d, int multi)
|
||||
ca_parse_line(Cadef d, int multi, int first)
|
||||
{
|
||||
Caarg adef, ddef;
|
||||
Caopt ptr, wasopt, dopt;
|
||||
|
@ -1148,16 +1232,17 @@ ca_parse_line(Cadef d, int multi)
|
|||
|
||||
/* Free old state. */
|
||||
|
||||
if (ca_alloced) {
|
||||
int i = ca_laststate.nopts;
|
||||
LinkList *p = ca_laststate.oargs;
|
||||
if (first && ca_alloced) {
|
||||
Castate s = &ca_laststate, ss;
|
||||
int f = 1;
|
||||
|
||||
freelinklist(ca_laststate.args, freestr);
|
||||
while (i--)
|
||||
if (*p++)
|
||||
freelinklist(p[-1], freestr);
|
||||
|
||||
zfree(ca_laststate.oargs, ca_laststate.d->nopts * sizeof(LinkList));
|
||||
while (s) {
|
||||
ss = s->snext;
|
||||
freecastate(s);
|
||||
if (!f)
|
||||
zfree(s, sizeof(*s));
|
||||
s = ss;
|
||||
}
|
||||
}
|
||||
/* Mark everything as active. */
|
||||
|
||||
|
@ -1171,6 +1256,7 @@ ca_parse_line(Cadef d, int multi)
|
|||
|
||||
/* Default values for the state. */
|
||||
|
||||
state.snext = NULL;
|
||||
state.d = d;
|
||||
state.nopts = d->nopts;
|
||||
state.def = state.ddef = NULL;
|
||||
|
@ -1482,16 +1568,13 @@ ca_colonlist(LinkList l)
|
|||
}
|
||||
|
||||
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;
|
||||
int restr = 0, onum, miss = 0, rest, oopt = 1, lopt = 0, addopt;
|
||||
|
||||
descr = newlinklist();
|
||||
act = newlinklist();
|
||||
subc = newlinklist();
|
||||
|
||||
rec:
|
||||
|
||||
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)
|
||||
oopt = 0;
|
||||
|
||||
addlinknode(descr, arg->descr);
|
||||
addlinknode(act, arg->action);
|
||||
for (dnode = firstnode(descr), anode = firstnode(act);
|
||||
dnode; incnode(dnode), incnode(anode))
|
||||
if (!strcmp((char *) getdata(dnode), arg->descr) &&
|
||||
!strcmp((char *) getdata(anode), arg->action))
|
||||
break;
|
||||
|
||||
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 (!dnode) {
|
||||
addlinknode(descr, arg->descr);
|
||||
addlinknode(act, arg->action);
|
||||
|
||||
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)
|
||||
break;
|
||||
|
||||
|
@ -1565,15 +1655,13 @@ ca_set_data(char *opt, Caarg arg, char **args, int single)
|
|||
|
||||
goto rec;
|
||||
}
|
||||
set_list_array(args[0], descr);
|
||||
set_list_array(args[1], act);
|
||||
set_list_array(args[2], subc);
|
||||
}
|
||||
|
||||
static int
|
||||
bin_comparguments(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
int min, max, n;
|
||||
Castate lstate = &ca_laststate;
|
||||
|
||||
if (incompfunc != 1) {
|
||||
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;
|
||||
}
|
||||
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 'O': min = 4; 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]) {
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (compcurrent > 1 && compwords[0]) {
|
||||
Cadef def;
|
||||
int cap = ca_parsed;
|
||||
LinkList cax = ca_xor;
|
||||
int cap = ca_parsed, multi, first = 1, use, ret = 0;
|
||||
LinkList cax = ca_xor, nx;
|
||||
LinkNode node;
|
||||
Castate states = NULL, sp;
|
||||
char *xor[2];
|
||||
|
||||
ca_parsed = 0;
|
||||
xor[1] = NULL;
|
||||
|
||||
if (args[0][1] == 'I') {
|
||||
char **xor;
|
||||
if (!(def = get_cadef(nam, args + 1)))
|
||||
return 1;
|
||||
|
||||
if (!(def = get_cadef(nam, args + 2, 1)))
|
||||
return 1;
|
||||
multi = !!def->snext;
|
||||
ca_parsed = cap;
|
||||
ca_xor = (multi ? newlinklist() : NULL);
|
||||
|
||||
ca_parsed = cap;
|
||||
ca_xor = newlinklist();
|
||||
if ((xor = getaparam(args[1]))) {
|
||||
if (arrcontains(xor, args[2], 0) ||
|
||||
ca_inactive(def, xor, compcurrent, 0)) {
|
||||
ca_xor = cax;
|
||||
return 1;
|
||||
while (def) {
|
||||
use = !ca_parse_line(def, multi, first);
|
||||
nx = ca_xor;
|
||||
ca_xor = NULL;
|
||||
while ((def = def->snext)) {
|
||||
if (nx) {
|
||||
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 = cax;
|
||||
return 1;
|
||||
ca_xor = nx;
|
||||
if (use && def) {
|
||||
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);
|
||||
} else {
|
||||
if (!(def = get_cadef(nam, args + 1, 0)))
|
||||
return 1;
|
||||
|
||||
ca_parsed = cap;
|
||||
ca_xor = NULL;
|
||||
ca_parse_line(def, 0);
|
||||
first = 0;
|
||||
}
|
||||
ca_xor = cax;
|
||||
ca_parsed = 1;
|
||||
ca_laststate.snext = states;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 'D':
|
||||
{
|
||||
Caarg arg = ca_laststate.def;
|
||||
LinkList descr, act, subc;
|
||||
Caarg arg;
|
||||
int ign = 0, ret = 1;
|
||||
|
||||
if (arg) {
|
||||
if (ca_laststate.doff > 0)
|
||||
ignore_prefix(ca_laststate.doff);
|
||||
descr = newlinklist();
|
||||
act = newlinklist();
|
||||
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':
|
||||
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 direct = newlinklist();
|
||||
LinkList odirect = newlinklist();
|
||||
LinkList equal = newlinklist(), l;
|
||||
Caopt p;
|
||||
char *str;
|
||||
int ret = 1;
|
||||
|
||||
for (p = ca_laststate.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;
|
||||
for (; lstate; lstate = lstate->snext) {
|
||||
if (lstate->actopts &&
|
||||
(lstate->opt || (lstate->doff && lstate->def) ||
|
||||
(lstate->def &&
|
||||
(lstate->def->type == CAA_OPT ||
|
||||
(lstate->def->type >= CAA_RARGS &&
|
||||
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);
|
||||
set_list_array(args[2], direct);
|
||||
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);
|
||||
if (!ret) {
|
||||
set_list_array(args[1], next);
|
||||
set_list_array(args[2], direct);
|
||||
set_list_array(args[3], odirect);
|
||||
set_list_array(args[4], equal);
|
||||
|
||||
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':
|
||||
if (ca_laststate.d->single && ca_laststate.singles &&
|
||||
ca_laststate.actopts && ca_laststate.opt) {
|
||||
setsparam(args[1],
|
||||
ztrdup((ca_laststate.ddef && ca_laststate.dopt) ?
|
||||
(ca_laststate.dopt->type == CAO_DIRECT ?
|
||||
"direct" :
|
||||
((ca_laststate.dopt->type == CAO_OEQUAL ||
|
||||
ca_laststate.dopt->type == CAO_EQUAL) ?
|
||||
"equal" : "next")) : ""));
|
||||
return 0;
|
||||
}
|
||||
for (; lstate; lstate = lstate->snext)
|
||||
if (lstate->d->single && lstate->singles &&
|
||||
lstate->actopts && lstate->opt) {
|
||||
setsparam(args[1],
|
||||
ztrdup((lstate->ddef && lstate->dopt) ?
|
||||
(lstate->dopt->type == CAO_DIRECT ?
|
||||
"direct" :
|
||||
((lstate->dopt->type == CAO_OEQUAL ||
|
||||
lstate->dopt->type == CAO_EQUAL) ?
|
||||
"equal" : "next")) : ""));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case 'M':
|
||||
setsparam(args[1], ztrdup(ca_laststate.d->match));
|
||||
return 0;
|
||||
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':
|
||||
{
|
||||
Castate s;
|
||||
char **ret, **p;
|
||||
LinkNode n;
|
||||
LinkList *a;
|
||||
Caopt o;
|
||||
int num;
|
||||
|
||||
ret = p = zalloc((countlinknodes(ca_laststate.args) + 1) *
|
||||
sizeof(char *));
|
||||
for (num = 0, s = lstate; s; s = s->snext)
|
||||
num += countlinknodes(s->args);
|
||||
|
||||
for (n = firstnode(ca_laststate.args); n; incnode(n))
|
||||
*p++ = ztrdup((char *) getdata(n));
|
||||
ret = p = zalloc((num + 1) * sizeof(char *));
|
||||
|
||||
for (s = lstate; s; s = s->snext)
|
||||
for (n = firstnode(s->args); n; incnode(n))
|
||||
*p++ = ztrdup((char *) getdata(n));
|
||||
*p = NULL;
|
||||
|
||||
setaparam(args[1], ret);
|
||||
|
||||
for (num = 0, o = ca_laststate.d->opts, a = ca_laststate.oargs; o;
|
||||
o = o->next, a++)
|
||||
if (*a)
|
||||
num += 2;
|
||||
for (num = 0, s = lstate; s; s = s->snext)
|
||||
for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
|
||||
if (*a)
|
||||
num += 2;
|
||||
|
||||
ret = p = zalloc((num + 1) * sizeof(char *));
|
||||
|
||||
for (o = ca_laststate.d->opts, a = ca_laststate.oargs; o;
|
||||
o = o->next, a++) {
|
||||
if (*a) {
|
||||
*p++ = (o->set ? tricat(o->set, o->name, "") :
|
||||
ztrdup(o->name));
|
||||
*p++ = ca_colonlist(*a);
|
||||
}
|
||||
}
|
||||
for (s = lstate; s; s = s->snext)
|
||||
for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
|
||||
if (*a) {
|
||||
*p++ = (o->set ? tricat(o->set, o->name, "") :
|
||||
ztrdup(o->name));
|
||||
*p++ = ca_colonlist(*a);
|
||||
}
|
||||
*p = NULL;
|
||||
|
||||
sethparam(args[2], ret);
|
||||
|
|
Loading…
Reference in a new issue