mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 22:11:54 +02:00
zsh-workers/9677
This commit is contained in:
parent
55b8857726
commit
3076ed44d3
12 changed files with 275 additions and 361 deletions
|
@ -26,14 +26,7 @@
|
|||
setopt localoptions extendedglob nobadpattern # xtrace promptsubst
|
||||
# local PS4='%N:%i:$((#key))> '
|
||||
|
||||
# Took me ages to work this out. If we're not on the first global
|
||||
# matcher specification, we mustn't do any I/O.
|
||||
if [[ compstate[matcher] -gt 1 && -z $_read_comp ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ compstate[matcher] -gt 1 ||
|
||||
( ${+NUMERIC} = 0 && -n $_read_comp ) ]]; then
|
||||
if [[ ${+NUMERIC} = 0 && -n $_read_comp ]]; then
|
||||
if [[ $_read_comp = _* ]]; then
|
||||
eval $_read_comp
|
||||
else
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
local _comp_correct _correct_expl comax cfgacc
|
||||
local curcontext="${curcontext}" oldcontext opm="$compstate[pattern_match]"
|
||||
|
||||
# Only if all global matchers have been tried.
|
||||
|
||||
[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
|
||||
|
||||
# We don't try correction if the string is too short.
|
||||
|
||||
[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
|
||||
|
@ -60,16 +56,7 @@ compadd() {
|
|||
builtin compadd "$_correct_expl[@]" "$@"
|
||||
}
|
||||
|
||||
# Now initialise our counter. We also set `compstate[matcher]'
|
||||
# to `-1'. This allows completion functions to use the simple
|
||||
# `[[ compstate[matcher] -gt 1 ]] && return' to avoid being
|
||||
# called for multiple global match specs and still be called
|
||||
# again when correction is done. Also, this makes it easy to
|
||||
# test if correction is attempted since `compstate[matcher]'
|
||||
# will never be set to a negative value by the completion code.
|
||||
|
||||
_comp_correct=1
|
||||
compstate[matcher]=-1
|
||||
|
||||
[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
|
||||
|
||||
|
@ -98,7 +85,6 @@ while [[ _comp_correct -le comax ]]; do
|
|||
[[ "$compstate[list]" != list* ]] &&
|
||||
compstate[list]="$compstate[list] force"
|
||||
fi
|
||||
compstate[matcher]="$compstate[total_matchers]"
|
||||
unfunction compadd
|
||||
compstate[pattern_match]="$opm"
|
||||
|
||||
|
@ -109,7 +95,6 @@ while [[ _comp_correct -le comax ]]; do
|
|||
(( _comp_correct++ ))
|
||||
done
|
||||
|
||||
compstate[matcher]="$compstate[total_matchers]"
|
||||
unfunction compadd
|
||||
compstate[pattern_match]="$opm"
|
||||
|
||||
|
|
|
@ -18,10 +18,6 @@ if zstyle -s ":completion:${curcontext}:" completions expr &&
|
|||
return 1
|
||||
fi
|
||||
|
||||
# Do this only for the first global matcher.
|
||||
|
||||
[[ "$compstate[matcher]" -le 1 ]] || return 1
|
||||
|
||||
# In exp we will collect the expansion.
|
||||
|
||||
exp=("$word")
|
||||
|
|
|
@ -128,8 +128,7 @@ if (( $compstate[nmatches] )); then
|
|||
fi
|
||||
fi
|
||||
fi
|
||||
elif [[ compstate[matcher] -eq compstate[total_matchers] &&
|
||||
$#_lastdescr -ne 0 ]] &&
|
||||
elif [[ $#_lastdescr -ne 0 ]] &&
|
||||
zstyle -s ":completion:${curcontext}:warnings" format format; then
|
||||
local str
|
||||
|
||||
|
@ -148,34 +147,30 @@ elif [[ compstate[matcher] -eq compstate[total_matchers] &&
|
|||
compadd -UX "$format" -n ''
|
||||
fi
|
||||
|
||||
if [[ compstate[matcher] -eq compstate[total_matchers] ||
|
||||
compstate[nmatches] -ne 0 ]]; then
|
||||
# See which tags were or were not used.
|
||||
|
||||
# See which tags were or were not used.
|
||||
_used_tags=( "${(@)_tried_tags:#${(j:|:)~${(@)_failed_tags//\[/\\[}//\]/\\]}}" )
|
||||
_unused_tags=( "${(@)_offered_tags:#${(j:|:)~${(@)_used_tags//\[/\\[}//\]/\\]}}" )
|
||||
|
||||
_used_tags=( "${(@)_tried_tags:#${(j:|:)~${(@)_failed_tags//\[/\\[}//\]/\\]}}" )
|
||||
_unused_tags=( "${(@)_offered_tags:#${(j:|:)~${(@)_used_tags//\[/\\[}//\]/\\]}}" )
|
||||
# Now call the post-functions.
|
||||
|
||||
# Now call the post-functions.
|
||||
for post in "$comppostfuncs[@]"; do
|
||||
"$post"
|
||||
done
|
||||
comppostfuncs=()
|
||||
|
||||
for post in "$comppostfuncs[@]"; do
|
||||
"$post"
|
||||
done
|
||||
comppostfuncs=()
|
||||
|
||||
_lastcomp=( "${(@kv)compstate}" )
|
||||
_lastcomp[completer]="$comp"
|
||||
_lastcomp[prefix]="$PREFIX"
|
||||
_lastcomp[suffix]="$SUFFIX"
|
||||
_lastcomp[iprefix]="$IPREFIX"
|
||||
_lastcomp[isuffix]="$ISUFFIX"
|
||||
_lastcomp[qiprefix]="$QIPREFIX"
|
||||
_lastcomp[qisuffix]="$QISUFFIX"
|
||||
_lastcomp[offered_tags]="${(j.:.)_offered_tags}"
|
||||
_lastcomp[tried_tags]="${(j.:.)_tried_tags}"
|
||||
_lastcomp[failed_tags]="${(j.:.)_failed_tags}"
|
||||
_lastcomp[unused_tags]="${(j.:.)_unused_tags}"
|
||||
_lastcomp[used_tags]="${(j.:.)_used_tags}"
|
||||
fi
|
||||
_lastcomp=( "${(@kv)compstate}" )
|
||||
_lastcomp[completer]="$comp"
|
||||
_lastcomp[prefix]="$PREFIX"
|
||||
_lastcomp[suffix]="$SUFFIX"
|
||||
_lastcomp[iprefix]="$IPREFIX"
|
||||
_lastcomp[isuffix]="$ISUFFIX"
|
||||
_lastcomp[qiprefix]="$QIPREFIX"
|
||||
_lastcomp[qisuffix]="$QISUFFIX"
|
||||
_lastcomp[offered_tags]="${(j.:.)_offered_tags}"
|
||||
_lastcomp[tried_tags]="${(j.:.)_tried_tags}"
|
||||
_lastcomp[failed_tags]="${(j.:.)_failed_tags}"
|
||||
_lastcomp[unused_tags]="${(j.:.)_unused_tags}"
|
||||
_lastcomp[used_tags]="${(j.:.)_used_tags}"
|
||||
|
||||
return ret
|
||||
|
|
|
@ -12,12 +12,10 @@
|
|||
local tmp opm="$compstate[pattern_match]" ret=0 orig ins
|
||||
local curcontext="${curcontext/:[^:]#:/:match:}"
|
||||
|
||||
# Do nothing if we don't have a pattern or there are still global
|
||||
# match specifications to try.
|
||||
# Do nothing if we don't have a pattern.
|
||||
|
||||
tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
|
||||
[[ "$tmp:q" = "$tmp" ||
|
||||
compstate[matcher] -ne compstate[total_matchers] ]] && return 1
|
||||
[[ "$tmp:q" = "$tmp" ]] && return 1
|
||||
|
||||
zstyle -s ":completion:${curcontext}:" original orig
|
||||
zstyle -b ":completion:${curcontext}:" insert-unambiguous ins
|
||||
|
@ -25,11 +23,9 @@ zstyle -b ":completion:${curcontext}:" insert-unambiguous ins
|
|||
# Try completion without inserting a `*'?
|
||||
|
||||
if [[ -n "$orig" ]]; then
|
||||
compstate[matcher]=-1
|
||||
compstate[pattern_match]='-'
|
||||
_complete && ret=1
|
||||
compstate[pattern_match]="$opm"
|
||||
compstate[matcher]="$compstate[total_matchers]"
|
||||
|
||||
if (( ret )); then
|
||||
[[ "$ins" = yes &&
|
||||
|
@ -43,11 +39,9 @@ fi
|
|||
|
||||
[[ "$orig" = only ]] && return 1
|
||||
|
||||
compstate[matcher]=-1
|
||||
compstate[pattern_match]='*'
|
||||
_complete && ret=1
|
||||
compstate[pattern_match]="$opm"
|
||||
compstate[matcher]="$compstate[total_matchers]"
|
||||
|
||||
[[ ret -eq 1 && "$ins" = yes &&
|
||||
$#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] &&
|
||||
|
|
|
@ -131,10 +131,19 @@ the default. In other words, completion will subsequently use the
|
|||
options specified by the tt(-D) flag.
|
||||
|
||||
The form with tt(-M) as the first and only option defines global
|
||||
matching specifications, as described in
|
||||
matching specifications (see
|
||||
ifzman(zshcompwid)\
|
||||
ifnzman(noderef(Matching Control))\
|
||||
.
|
||||
). The match specifications given will be used for every completion
|
||||
attempt (only when using tt(compctl), not with the new completion
|
||||
system) and are tried in the order in which they are defined until one
|
||||
generates at least one match. E.g.:
|
||||
|
||||
example(compctl -M '' 'm:{a-zA-Z}={A-Za-z}')
|
||||
|
||||
This will first try completion without any global match specifications
|
||||
(the empty string) and, if that generates no matches, will try case
|
||||
insensitive completion.
|
||||
|
||||
texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion Using compctl)
|
||||
sect(Option Flags)
|
||||
|
|
|
@ -12,17 +12,6 @@ completion code. The shell functions of the second set which implement
|
|||
completion behaviour and which may be bound to keystrokes, are referred to
|
||||
as `widgets'.
|
||||
|
||||
Note that with the function-based completions described here, it
|
||||
is also possible to use the
|
||||
tt(compmatchers) special array to specify
|
||||
global matching control, such as case-insensitivity (`tt(abc)' will complete
|
||||
to a string beginning `tt(ABC)'), or wildcard behaviour on
|
||||
certain anchors (`tt(a-d)' will complete to abc-def as if there were a
|
||||
`tt(*)' after the `a'). See
|
||||
ifzman(the section `Matching Control' in zmanref(zshcompwid))\
|
||||
ifnzman(noderef(Matching Control))
|
||||
for further details.
|
||||
|
||||
Note also, that it is possible to use old completion definitions using
|
||||
the tt(compctl) builtin command together with the functions for the
|
||||
new completion system. To enable this, the tt(_default) function from
|
||||
|
@ -1594,7 +1583,8 @@ This completer allows to define a match specification (see
|
|||
ifzman(the section `Matching Control' in zmanref(zshcompwid))\
|
||||
ifnzman(noderef(Matching Control))\
|
||||
) that is to be used by all following completers. This is comparable
|
||||
to the tt(compmatchers) special array, but gives finer control. The match
|
||||
to the global match specifications that can be defined for the
|
||||
tt(compctl) builtin, but gives much better control. The match
|
||||
specification to use is looked up using the tt(matcher) style. For
|
||||
this, the completer field of the context name will contain the string
|
||||
`tt(matcher-)var(n)', where `var(n)' is the number of the call to
|
||||
|
|
|
@ -207,21 +207,6 @@ names with one of the suffixes from the tt(fignore) array and matches
|
|||
put into the alternate set using the tt(-a) option of the tt(compadd)
|
||||
builtin command (see below) are not counted.
|
||||
)
|
||||
item(tt(matcher))(
|
||||
When completion is performed with a global match specification as defined
|
||||
by
|
||||
|
||||
indent(tt(compmatchers=)tt(LPAR()) var(spec1 ... specN ...) tt(RPAR()))
|
||||
|
||||
this gives the number of the specification string currently in use.
|
||||
In this case, matching is performed with each specification in turn.
|
||||
)
|
||||
item(tt(matcher_string))(
|
||||
The global match specification string var(specN) currently used.
|
||||
)
|
||||
item(tt(total_matchers))(
|
||||
The total number of global match specifications.
|
||||
)
|
||||
item(tt(restore))(
|
||||
This is set to tt(auto) before a function is entered, which forces the
|
||||
special parameters mentioned above (tt(words), tt(CURRENT), tt(PREFIX),
|
||||
|
@ -741,7 +726,7 @@ enditem()
|
|||
texinode(Matching Control)(Examples)(Condition Codes)(Completion Widgets)
|
||||
sect(Matching Control)
|
||||
|
||||
It is possible by use of the tt(compmatchers) special array and the
|
||||
It is possible by use of the
|
||||
tt(-M) option of the tt(compadd) builtin command to specify how the
|
||||
characters in the string to be completed (referred to here as the
|
||||
command line) map onto the characters in the list of matches produced by
|
||||
|
@ -842,17 +827,16 @@ specification characters (tt(L) and tt(M)) guarantees that what has
|
|||
already been typed on the command line (in particular the prefix
|
||||
tt(no)) will not be deleted.
|
||||
|
||||
The second example makes completion case insensitive. By setting the
|
||||
tt(compmatchers) array this applies to every
|
||||
completion. This is just the same as in the option example, except
|
||||
here we wish to retain the characters in the list of completions:
|
||||
The second example makes completion case insensitive. This is just
|
||||
the same as in the option example, except here we wish to retain the
|
||||
characters in the list of completions:
|
||||
|
||||
example(compmatchers=( 'm:{a-z}={A-Z}' ) )
|
||||
example(compadd -M 'm:{a-z}={A-Z}' ... )
|
||||
|
||||
This makes lowercase letters match their uppercase counterparts.
|
||||
To make uppercase letters match the lowercase forms as well:
|
||||
|
||||
example(compmatchers=( 'm:{a-zA-Z}={A-Za-z}' ) )
|
||||
example(compadd -M 'm:{a-zA-Z}={A-Za-z}' ... )
|
||||
|
||||
A nice example for the use of tt(*) patterns is partial word
|
||||
completion. Sometimes you would like to make strings like tt(c.s.u)
|
||||
|
@ -889,37 +873,21 @@ at the end of the trial completion.
|
|||
|
||||
More generally, the specification
|
||||
|
||||
example(compmatchers=( 'r:|[.,_-]=* r:|=*' ) )
|
||||
example(compadd -M 'r:|[.,_-]=* r:|=*' ... )
|
||||
|
||||
allows one to complete words with abbreviations before any of the
|
||||
characters in the square brackets in any completion. For example, to
|
||||
characters in the square brackets. For example, to
|
||||
complete tt(veryverylongfile.c) rather than tt(veryverylongheader.h)
|
||||
with the above in effect, you can just type tt(very.c) before attempting
|
||||
completion.
|
||||
|
||||
The tt(compmatchers) array that defines global matching can actually
|
||||
contain any number of specification strings, unlike the case where the
|
||||
tt(-M) option is used with the tt(compadd) builtin command. In this case, when
|
||||
completion is attempted for any command, the code will try the
|
||||
specifications in order until one matches. This allows one to define
|
||||
simple and fast matches to be used first, more powerful matchers as a
|
||||
second choice, and so on.
|
||||
|
||||
For example, one can make the code match trial completions that contain
|
||||
the string on the command line as a substring, not just at the
|
||||
beginning. Since this might produce more matches than we want,
|
||||
we arrange for it to be tried only if the matchers described above don't
|
||||
produce any matches:
|
||||
|
||||
example(compmatchers=( 'r:|[.,_-]=* r:|=*' 'l:|=* r:|=*' ) )
|
||||
|
||||
Here, if the string on the command line is tt(foo.bar), the completion
|
||||
code first tries matching tt(foo)var(anything)tt(.bar)var(anything), as
|
||||
with the previous example. If that fails, the two descriptions in the
|
||||
second string say that the blanks at the beginning
|
||||
and end of the string on the command line can match any set of
|
||||
characters at the beginning or end of the trial completion, so it will
|
||||
look for var(anything)tt(foo.bar)var(anything).
|
||||
When using the completion system (see
|
||||
ifzman(zmanref(zshcompsys))\
|
||||
ifnzman(noderef(Completion System))\
|
||||
), users can define match specifications that are to be used for
|
||||
specific contexts by using the tt(matcher) style and match
|
||||
specifications that are to be used everywhere can be defined by the
|
||||
use of the tt(_matcher) completer.
|
||||
|
||||
texinode(Examples)()(Matching Control)(Completion Widgets)
|
||||
sect(Examples)
|
||||
|
|
|
@ -309,70 +309,62 @@ typedef void (*CLPrintFunc)(Cmgroup, Cmatch *, int, int, int, int,
|
|||
|
||||
#define CPN_NMATCHES 0
|
||||
#define CP_NMATCHES (1 << CPN_NMATCHES)
|
||||
#define CPN_MATCHER 1
|
||||
#define CP_MATCHER (1 << CPN_MATCHER)
|
||||
#define CPN_MATCHERSTR 2
|
||||
#define CP_MATCHERSTR (1 << CPN_MATCHERSTR)
|
||||
#define CPN_MATCHERTOT 3
|
||||
#define CP_MATCHERTOT (1 << CPN_MATCHERTOT)
|
||||
#define CPN_CONTEXT 4
|
||||
#define CPN_CONTEXT 1
|
||||
#define CP_CONTEXT (1 << CPN_CONTEXT)
|
||||
#define CPN_PARAMETER 5
|
||||
#define CPN_PARAMETER 2
|
||||
#define CP_PARAMETER (1 << CPN_PARAMETER)
|
||||
#define CPN_REDIRECT 6
|
||||
#define CPN_REDIRECT 3
|
||||
#define CP_REDIRECT (1 << CPN_REDIRECT)
|
||||
#define CPN_QUOTE 7
|
||||
#define CPN_QUOTE 4
|
||||
#define CP_QUOTE (1 << CPN_QUOTE)
|
||||
#define CPN_QUOTING 8
|
||||
#define CPN_QUOTING 5
|
||||
#define CP_QUOTING (1 << CPN_QUOTING)
|
||||
#define CPN_RESTORE 9
|
||||
#define CPN_RESTORE 6
|
||||
#define CP_RESTORE (1 << CPN_RESTORE)
|
||||
#define CPN_LIST 10
|
||||
#define CPN_LIST 7
|
||||
#define CP_LIST (1 << CPN_LIST)
|
||||
#define CPN_INSERT 11
|
||||
#define CPN_INSERT 8
|
||||
#define CP_INSERT (1 << CPN_INSERT)
|
||||
#define CPN_EXACT 12
|
||||
#define CPN_EXACT 9
|
||||
#define CP_EXACT (1 << CPN_EXACT)
|
||||
#define CPN_EXACTSTR 13
|
||||
#define CPN_EXACTSTR 10
|
||||
#define CP_EXACTSTR (1 << CPN_EXACTSTR)
|
||||
#define CPN_PATMATCH 14
|
||||
#define CPN_PATMATCH 11
|
||||
#define CP_PATMATCH (1 << CPN_PATMATCH)
|
||||
#define CPN_PATINSERT 15
|
||||
#define CPN_PATINSERT 12
|
||||
#define CP_PATINSERT (1 << CPN_PATINSERT)
|
||||
#define CPN_UNAMBIG 16
|
||||
#define CPN_UNAMBIG 13
|
||||
#define CP_UNAMBIG (1 << CPN_UNAMBIG)
|
||||
#define CPN_UNAMBIGC 17
|
||||
#define CPN_UNAMBIGC 14
|
||||
#define CP_UNAMBIGC (1 << CPN_UNAMBIGC)
|
||||
#define CPN_LISTMAX 18
|
||||
#define CPN_LISTMAX 15
|
||||
#define CP_LISTMAX (1 << CPN_LISTMAX)
|
||||
#define CPN_LASTPROMPT 19
|
||||
#define CPN_LASTPROMPT 16
|
||||
#define CP_LASTPROMPT (1 << CPN_LASTPROMPT)
|
||||
#define CPN_TOEND 20
|
||||
#define CPN_TOEND 17
|
||||
#define CP_TOEND (1 << CPN_TOEND)
|
||||
#define CPN_OLDLIST 21
|
||||
#define CPN_OLDLIST 18
|
||||
#define CP_OLDLIST (1 << CPN_OLDLIST)
|
||||
#define CPN_OLDINS 22
|
||||
#define CPN_OLDINS 19
|
||||
#define CP_OLDINS (1 << CPN_OLDINS)
|
||||
#define CPN_VARED 23
|
||||
#define CPN_VARED 20
|
||||
#define CP_VARED (1 << CPN_VARED)
|
||||
#define CPN_ANMATCHES 24
|
||||
#define CPN_ANMATCHES 21
|
||||
#define CP_ANMATCHES (1 << CPN_ANMATCHES)
|
||||
#define CPN_LISTLINES 25
|
||||
#define CPN_LISTLINES 22
|
||||
#define CP_LISTLINES (1 << CPN_LISTLINES)
|
||||
#define CPN_QUOTES 26
|
||||
#define CPN_QUOTES 23
|
||||
#define CP_QUOTES (1 << CPN_QUOTES)
|
||||
|
||||
#define CP_KEYPARAMS 27
|
||||
#define CP_ALLKEYS ((unsigned int) 0x7ffffff)
|
||||
#define CP_KEYPARAMS 24
|
||||
#define CP_ALLKEYS ((unsigned int) 0xffffff)
|
||||
|
||||
/* Hooks. */
|
||||
|
||||
#define INSERTMATCHHOOK (comphooks + 0)
|
||||
#define MENUSTARTHOOK (comphooks + 1)
|
||||
#define COMPCTLMAKEHOOK (comphooks + 2)
|
||||
#define COMPCTLBEFOREHOOK (comphooks + 3)
|
||||
#define COMPCTLAFTERHOOK (comphooks + 4)
|
||||
#define COMPLISTMATCHESHOOK (comphooks + 5)
|
||||
#define COMPLISTMATCHESHOOK (comphooks + 3)
|
||||
|
||||
/* compctl hook data struct */
|
||||
|
||||
|
|
|
@ -808,59 +808,21 @@ callcompfunc(char *s, char *fn)
|
|||
static int
|
||||
makecomplist(char *s, int incmd, int lst)
|
||||
{
|
||||
struct cmlist ms;
|
||||
Cmlist m;
|
||||
char *p, *os = s;
|
||||
int onm = nmatches, osi = movefd(0);
|
||||
char *p;
|
||||
|
||||
/* Inside $... ? */
|
||||
if (compfunc && (p = check_param(s, 0, 0)))
|
||||
os = s = p;
|
||||
|
||||
/* We build a copy of the list of matchers to use to make sure that this
|
||||
* works even if a shell function called from the completion code changes
|
||||
* the global matchers. */
|
||||
|
||||
if ((m = cmatcher)) {
|
||||
Cmlist mm, *mp = &mm;
|
||||
int n;
|
||||
|
||||
for (n = 0; m; m = m->next, n++) {
|
||||
*mp = (Cmlist) zhalloc(sizeof(struct cmlist));
|
||||
(*mp)->matcher = m->matcher;
|
||||
(*mp)->next = NULL;
|
||||
(*mp)->str = dupstring(m->str);
|
||||
mp = &((*mp)->next);
|
||||
addlinknode(matchers, m->matcher);
|
||||
if (m->matcher)
|
||||
m->matcher->refc++;
|
||||
}
|
||||
m = mm;
|
||||
compmatcher = 1;
|
||||
compmatchertot = n;
|
||||
} else
|
||||
compmatcher = 0;
|
||||
s = p;
|
||||
|
||||
linwhat = inwhat;
|
||||
|
||||
/* Walk through the global matchers. */
|
||||
for (;;) {
|
||||
bmatchers = NULL;
|
||||
zsfree(compmatcherstr);
|
||||
if (m) {
|
||||
ms.next = NULL;
|
||||
ms.matcher = m->matcher;
|
||||
mstack = &ms;
|
||||
if (compfunc) {
|
||||
char *os = s;
|
||||
int onm = nmatches, osi = movefd(0);
|
||||
|
||||
bmatchers = NULL;
|
||||
mstack = NULL;
|
||||
|
||||
/* Store the matchers used in the bmatchers list which is used
|
||||
* when building new parts for the string to insert into the
|
||||
* line. */
|
||||
add_bmatchers(m->matcher);
|
||||
compmatcherstr = ztrdup(m->str);
|
||||
} else {
|
||||
mstack = NULL;
|
||||
compmatcherstr = ztrdup("");
|
||||
}
|
||||
ainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
fainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
|
||||
|
@ -877,24 +839,10 @@ makecomplist(char *s, int incmd, int lst)
|
|||
begcmgroup("default", 0);
|
||||
menucmp = menuacc = newmatches = onlyexpl = 0;
|
||||
|
||||
runhookdef(COMPCTLBEFOREHOOK, NULL);
|
||||
|
||||
s = dupstring(os);
|
||||
if (compfunc)
|
||||
callcompfunc(s, compfunc);
|
||||
else {
|
||||
struct ccmakedat dat;
|
||||
|
||||
dat.str = s;
|
||||
dat.incmd = incmd;
|
||||
dat.lst = lst;
|
||||
runhookdef(COMPCTLMAKEHOOK, (void *) &dat);
|
||||
}
|
||||
callcompfunc(s, compfunc);
|
||||
endcmgroup(NULL);
|
||||
|
||||
runhookdef(COMPCTLAFTERHOOK,
|
||||
(void *) ((amatches && !oldlist) ? 1L : 0L));
|
||||
|
||||
if (oldlist) {
|
||||
nmatches = onm;
|
||||
validlist = 1;
|
||||
|
@ -933,14 +881,18 @@ makecomplist(char *s, int incmd, int lst)
|
|||
|
||||
return 0;
|
||||
}
|
||||
if (!m || !(m = m->next))
|
||||
break;
|
||||
redup(osi, 0);
|
||||
return 1;
|
||||
} else {
|
||||
struct ccmakedat dat;
|
||||
|
||||
errflag = 0;
|
||||
compmatcher++;
|
||||
dat.str = s;
|
||||
dat.incmd = incmd;
|
||||
dat.lst = lst;
|
||||
runhookdef(COMPCTLMAKEHOOK, (void *) &dat);
|
||||
|
||||
return dat.lst;
|
||||
}
|
||||
redup(osi, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
#include "compctl.mdh"
|
||||
#include "compctl.pro"
|
||||
|
||||
/* Global matcher. */
|
||||
|
||||
/**/
|
||||
static Cmlist cmatcher;
|
||||
|
||||
/* Default completion infos */
|
||||
|
||||
/**/
|
||||
|
@ -275,6 +280,53 @@ compctlread(char *name, char **args, char *ops, char *reply)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Copy a list of completion matchers. */
|
||||
|
||||
/**/
|
||||
static Cmlist
|
||||
cpcmlist(Cmlist l)
|
||||
{
|
||||
Cmlist r = NULL, *p = &r, n;
|
||||
|
||||
while (l) {
|
||||
*p = n = (Cmlist) zalloc(sizeof(struct cmlist));
|
||||
n->next = NULL;
|
||||
n->matcher = cpcmatcher(l->matcher);
|
||||
n->str = ztrdup(l->str);
|
||||
|
||||
p = &(n->next);
|
||||
l = l->next;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Set the global match specs. */
|
||||
|
||||
/**/
|
||||
static int
|
||||
set_gmatcher(char *name, char **argv)
|
||||
{
|
||||
Cmlist l = NULL, *q = &l, n;
|
||||
Cmatcher m;
|
||||
|
||||
while (*argv) {
|
||||
if ((m = parse_cmatcher(name, *argv)) == pcm_err)
|
||||
return 1;
|
||||
*q = n = (Cmlist) zhalloc(sizeof(struct cmlist));
|
||||
n->next = NULL;
|
||||
n->matcher = m;
|
||||
n->str = *argv++;
|
||||
|
||||
q = &(n->next);
|
||||
}
|
||||
freecmlist(cmatcher);
|
||||
PERMALLOC {
|
||||
cmatcher = cpcmlist(l);
|
||||
} LASTALLOC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Try to get the global matcher from the given compctl. */
|
||||
|
||||
/**/
|
||||
|
@ -1709,39 +1761,134 @@ static int addwhat;
|
|||
static int
|
||||
ccmakehookfn(Hookdef dummy, struct ccmakedat *dat)
|
||||
{
|
||||
makecomplistglobal(dat->str, dat->incmd, dat->lst, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ccbeforehookfn(Hookdef dummy, void *zdup)
|
||||
{
|
||||
ccused = newlinklist();
|
||||
ccstack = newlinklist();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ccafterhookfn(Hookdef dummy, void *zdup)
|
||||
{
|
||||
char *s = dat->str;
|
||||
int incmd = dat->incmd, lst = dat->lst;
|
||||
struct cmlist ms;
|
||||
Cmlist m;
|
||||
char *os = s;
|
||||
int onm = nmatches, osi = movefd(0);
|
||||
LinkNode n;
|
||||
|
||||
if (zdup) {
|
||||
if (lastccused)
|
||||
freelinklist(lastccused, (FreeFunc) freecompctl);
|
||||
/* We build a copy of the list of matchers to use to make sure that this
|
||||
* works even if a shell function called from the completion code changes
|
||||
* the global matchers. */
|
||||
|
||||
PERMALLOC {
|
||||
lastccused = newlinklist();
|
||||
if ((m = cmatcher)) {
|
||||
Cmlist mm, *mp = &mm;
|
||||
int n;
|
||||
|
||||
for (n = 0; m; m = m->next, n++) {
|
||||
*mp = (Cmlist) zhalloc(sizeof(struct cmlist));
|
||||
(*mp)->matcher = m->matcher;
|
||||
(*mp)->next = NULL;
|
||||
(*mp)->str = dupstring(m->str);
|
||||
mp = &((*mp)->next);
|
||||
addlinknode(matchers, m->matcher);
|
||||
if (m->matcher)
|
||||
m->matcher->refc++;
|
||||
}
|
||||
m = mm;
|
||||
}
|
||||
|
||||
/* Walk through the global matchers. */
|
||||
for (;;) {
|
||||
bmatchers = NULL;
|
||||
if (m) {
|
||||
ms.next = NULL;
|
||||
ms.matcher = m->matcher;
|
||||
mstack = &ms;
|
||||
|
||||
/* Store the matchers used in the bmatchers list which is used
|
||||
* when building new parts for the string to insert into the
|
||||
* line. */
|
||||
add_bmatchers(m->matcher);
|
||||
} else
|
||||
mstack = NULL;
|
||||
|
||||
ainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
fainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
|
||||
freecl = NULL;
|
||||
|
||||
if (!validlist)
|
||||
lastambig = 0;
|
||||
amatches = NULL;
|
||||
mnum = 0;
|
||||
unambig_mnum = -1;
|
||||
isuf = NULL;
|
||||
insmnum = insgnum = 1;
|
||||
insgroup = oldlist = oldins = 0;
|
||||
begcmgroup("default", 0);
|
||||
menucmp = menuacc = newmatches = onlyexpl = 0;
|
||||
|
||||
ccused = newlinklist();
|
||||
ccstack = newlinklist();
|
||||
|
||||
s = dupstring(os);
|
||||
makecomplistglobal(s, incmd, lst, 0);
|
||||
endcmgroup(NULL);
|
||||
|
||||
if (amatches && !oldlist) {
|
||||
if (lastccused)
|
||||
freelinklist(lastccused, (FreeFunc) freecompctl);
|
||||
|
||||
PERMALLOC {
|
||||
lastccused = newlinklist();
|
||||
for (n = firstnode(ccused); n; incnode(n))
|
||||
addlinknode(lastccused, getdata(n));
|
||||
} LASTALLOC;
|
||||
} else
|
||||
for (n = firstnode(ccused); n; incnode(n))
|
||||
addlinknode(lastccused, getdata(n));
|
||||
} LASTALLOC;
|
||||
} else
|
||||
for (n = firstnode(ccused); n; incnode(n))
|
||||
if (((Compctl) getdata(n)) != &cc_dummy)
|
||||
freecompctl((Compctl) getdata(n));
|
||||
if (((Compctl) getdata(n)) != &cc_dummy)
|
||||
freecompctl((Compctl) getdata(n));
|
||||
|
||||
if (oldlist) {
|
||||
nmatches = onm;
|
||||
validlist = 1;
|
||||
amatches = lastmatches;
|
||||
lmatches = lastlmatches;
|
||||
if (pmatches) {
|
||||
freematches(pmatches);
|
||||
pmatches = NULL;
|
||||
hasperm = 0;
|
||||
}
|
||||
redup(osi, 0);
|
||||
|
||||
dat->lst = 0;
|
||||
return 0;
|
||||
}
|
||||
PERMALLOC {
|
||||
if (lastmatches) {
|
||||
freematches(lastmatches);
|
||||
lastmatches = NULL;
|
||||
}
|
||||
permmatches(1);
|
||||
amatches = pmatches;
|
||||
lastpermmnum = permmnum;
|
||||
lastpermgnum = permgnum;
|
||||
} LASTALLOC;
|
||||
|
||||
lastmatches = pmatches;
|
||||
lastlmatches = lmatches;
|
||||
pmatches = NULL;
|
||||
hasperm = 0;
|
||||
hasoldlist = 1;
|
||||
|
||||
if (nmatches && !errflag) {
|
||||
validlist = 1;
|
||||
|
||||
redup(osi, 0);
|
||||
|
||||
dat->lst = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!m || !(m = m->next))
|
||||
break;
|
||||
|
||||
errflag = 0;
|
||||
}
|
||||
redup(osi, 0);
|
||||
dat->lst = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3755,8 +3902,6 @@ int
|
|||
boot_(Module m)
|
||||
{
|
||||
addhookfunc("compctl_make", (Hookfn) ccmakehookfn);
|
||||
addhookfunc("compctl_before", (Hookfn) ccbeforehookfn);
|
||||
addhookfunc("compctl_after", (Hookfn) ccafterhookfn);
|
||||
return (addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) != 1);
|
||||
}
|
||||
|
||||
|
@ -3765,8 +3910,6 @@ int
|
|||
cleanup_(Module m)
|
||||
{
|
||||
deletehookfunc("compctl_make", (Hookfn) ccmakehookfn);
|
||||
deletehookfunc("compctl_before", (Hookfn) ccbeforehookfn);
|
||||
deletehookfunc("compctl_after", (Hookfn) ccafterhookfn);
|
||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,19 +30,12 @@
|
|||
#include "complete.mdh"
|
||||
#include "complete.pro"
|
||||
|
||||
/* Global matcher. */
|
||||
|
||||
/**/
|
||||
mod_export Cmlist cmatcher;
|
||||
|
||||
/* global variables for shell parameters in new style completion */
|
||||
|
||||
/**/
|
||||
mod_export zlong compcurrent;
|
||||
/**/
|
||||
zlong compmatcher,
|
||||
compmatchertot,
|
||||
complistmax,
|
||||
zlong complistmax,
|
||||
complistlines;
|
||||
|
||||
/**/
|
||||
|
@ -59,7 +52,6 @@ char **compwords,
|
|||
*complastprompt;
|
||||
/**/
|
||||
char *compiprefix,
|
||||
*compmatcherstr,
|
||||
*compcontext,
|
||||
*compparameter,
|
||||
*compredirect,
|
||||
|
@ -131,26 +123,6 @@ freecpattern(Cpattern p)
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy a list of completion matchers. */
|
||||
|
||||
/**/
|
||||
static Cmlist
|
||||
cpcmlist(Cmlist l)
|
||||
{
|
||||
Cmlist r = NULL, *p = &r, n;
|
||||
|
||||
while (l) {
|
||||
*p = n = (Cmlist) zalloc(sizeof(struct cmlist));
|
||||
n->next = NULL;
|
||||
n->matcher = cpcmatcher(l->matcher);
|
||||
n->str = ztrdup(l->str);
|
||||
|
||||
p = &(n->next);
|
||||
l = l->next;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Copy a completion matcher list. */
|
||||
|
||||
/**/
|
||||
|
@ -201,33 +173,6 @@ cpcpattern(Cpattern o)
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Set the global match specs. */
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
set_gmatcher(char *name, char **argv)
|
||||
{
|
||||
Cmlist l = NULL, *q = &l, n;
|
||||
Cmatcher m;
|
||||
|
||||
while (*argv) {
|
||||
if ((m = parse_cmatcher(name, *argv)) == pcm_err)
|
||||
return 1;
|
||||
*q = n = (Cmlist) zhalloc(sizeof(struct cmlist));
|
||||
n->next = NULL;
|
||||
n->matcher = m;
|
||||
n->str = *argv++;
|
||||
|
||||
q = &(n->next);
|
||||
}
|
||||
freecmlist(cmatcher);
|
||||
PERMALLOC {
|
||||
cmatcher = cpcmlist(l);
|
||||
} LASTALLOC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse a string for matcher control, containing multiple matchers. */
|
||||
|
||||
/**/
|
||||
|
@ -943,9 +888,6 @@ static struct compparam comprparams[] = {
|
|||
|
||||
static struct compparam compkparams[] = {
|
||||
{ "nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_nmatches) },
|
||||
{ "matcher", PM_INTEGER, VAL(compmatcher), NULL, NULL },
|
||||
{ "matcher_string", PM_SCALAR, VAL(compmatcherstr), NULL, NULL },
|
||||
{ "total_matchers", PM_INTEGER, VAL(compmatchertot), NULL, NULL },
|
||||
{ "context", PM_SCALAR, VAL(compcontext), NULL, NULL },
|
||||
{ "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL },
|
||||
{ "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL },
|
||||
|
@ -1322,42 +1264,6 @@ cond_range(char **a, int id)
|
|||
(id ? cond_str(a, 1, 1) : NULL), 0);
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
cmsetfn(Param pm, char **v)
|
||||
{
|
||||
set_gmatcher(pm->nam, v);
|
||||
}
|
||||
|
||||
/**/
|
||||
static char **
|
||||
cmgetfn(Param pm)
|
||||
{
|
||||
int num;
|
||||
Cmlist p;
|
||||
char **ret, **q;
|
||||
|
||||
for (num = 0, p = cmatcher; p; p = p->next, num++);
|
||||
|
||||
ret = (char **) zhalloc((num + 1) * sizeof(char *));
|
||||
|
||||
for (q = ret, p = cmatcher; p; p = p->next, q++)
|
||||
*q = dupstring(p->str);
|
||||
*q = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
cmunsetfn(Param pm, int exp)
|
||||
{
|
||||
char *dummy[1];
|
||||
|
||||
dummy[0] = NULL;
|
||||
set_gmatcher(pm->nam, dummy);
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("compset", 0, bin_compset, 1, 3, 0, NULL, NULL),
|
||||
|
@ -1374,10 +1280,6 @@ static struct funcwrap wrapper[] = {
|
|||
WRAPDEF(comp_wrapper),
|
||||
};
|
||||
|
||||
static struct paramdef patab[] = {
|
||||
PARAMDEF("compmatchers", PM_ARRAY|PM_SPECIAL, NULL, cmsetfn, cmgetfn, cmunsetfn)
|
||||
};
|
||||
|
||||
/* The order of the entries in this table has to match the *HOOK
|
||||
* macros in comp.h */
|
||||
|
||||
|
@ -1386,8 +1288,6 @@ struct hookdef comphooks[] = {
|
|||
HOOKDEF("insert_match", NULL, HOOKF_ALL),
|
||||
HOOKDEF("menu_start", NULL, HOOKF_ALL),
|
||||
HOOKDEF("compctl_make", NULL, 0),
|
||||
HOOKDEF("compctl_before", NULL, 0),
|
||||
HOOKDEF("compctl_after", NULL, 0),
|
||||
HOOKDEF("comp_list_matches", ilistmatches, 0),
|
||||
};
|
||||
|
||||
|
@ -1400,7 +1300,7 @@ setup_(Module m)
|
|||
comprpms = compkpms = NULL;
|
||||
compwords = NULL;
|
||||
compprefix = compsuffix = compiprefix = compisuffix =
|
||||
compqiprefix = compqisuffix = compmatcherstr =
|
||||
compqiprefix = compqisuffix =
|
||||
compcontext = compparameter = compredirect = compquote =
|
||||
compquoting = comprestore = complist = compinsert =
|
||||
compexact = compexactstr = comppatmatch = comppatinsert =
|
||||
|
@ -1426,7 +1326,6 @@ boot_(Module m)
|
|||
addhookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks));
|
||||
if (!(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
|
||||
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
|
||||
addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) |
|
||||
!addwrapper(m, wrapper)))
|
||||
return 1;
|
||||
return 0;
|
||||
|
@ -1446,7 +1345,6 @@ cleanup_(Module m)
|
|||
deletehookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks));
|
||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
|
||||
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
|
||||
deletewrapper(m, wrapper);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1463,7 +1361,6 @@ finish_(Module m)
|
|||
zsfree(compisuffix);
|
||||
zsfree(compqiprefix);
|
||||
zsfree(compqisuffix);
|
||||
zsfree(compmatcherstr);
|
||||
zsfree(compcontext);
|
||||
zsfree(compparameter);
|
||||
zsfree(compredirect);
|
||||
|
|
Loading…
Reference in a new issue