1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-16 12:21:18 +02:00

zsh-workers/8227

This commit is contained in:
Tanaka Akira 1999-10-13 13:43:02 +00:00
parent 18e3d1903d
commit ace2616432
11 changed files with 454 additions and 217 deletions

View file

@ -318,6 +318,12 @@ of the completer functions to decide if other completers should be
called. If the return value is zero, no other completers are tried and the
tt(_main_complete) function returns.
Immediately before returning the tt(_main_complete) function calls all
functions whose names are given in the tt(comppostfuncs) array and
then resets it to an empty array. This can be used by completion
functions or by other ZLE widgets calling completion to register code
that is to be executed after all matches have been added.
The widget function tt(_main_complete) also uses the configuration key
tt(last_prompt). If this is set to tt(always), the cursor is moved up
to the last prompt after printing a list of matches even if a numeric
@ -1718,10 +1724,14 @@ common prefix different from the word on the line or if there is such
a common prefix, respectively. The sequence `tt(%c)' is replaced by
the name of the completer function that generated the matches (without
the leading underscore). Finally, `tt(%n)' is replaced by the number
of matches generated and `tt(%a)' is replaced by an empty string if
of matches generated, `tt(%a)' is replaced by an empty string if
the matches are in the normal set (i.e. the one without file names
with one of the suffixes from the tt(fignore) array) and with `tt(
-alt-)' if the matches are in the alternate set.
-alt-)' if the matches are in the alternate set, and if the
tt(incremental_list) key (see below) is set, `tt(%l)' is replaced by
`tt(...)' if the list of matches is too long to fit on the screen and
with an empty string otherwise. If tt(incremental_list) is not set or
set to an empty string, `tt(%l)' will always be removed.
)
item(tt(incremental_stop))(
This gives a pattern matching (keyboard-) keys which will cause

View file

@ -184,10 +184,13 @@ When completing inside quotes, this contains the quotation character
is unset.
)
item(tt(nmatches))(
The number of matches generated and accepted by the completion code so far.
The number of matches generated and accepted by the completion code so
far, excluding those matches that are only accepted by ignoring the
tt(fignore) parameter and the tt(-a) option of the tt(compadd) builtin
command.
)
item(tt(normal_nmatches))(
Like tt(nmatches), but counts only matches in the normal set. I.e. file
item(tt(alternate_nmatches))(
Like tt(nmatches), but counts only matches in the alternate set. I.e. file
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.
@ -216,11 +219,14 @@ sets it to any other string, they will not be restored.
)
item(tt(list))(
This controls whether or how the list of matches will be displayed. If it
is unset or empty they will never be listed; if is set to tt(list), they
will always be listed; if tt(autolist) or tt(ambiguous), they will be
listed when the tt(AUTO_LIST) or tt(LIST_AMBIGUOUS) options respectively
would normally cause them to be. It will be set appropriately on entry to
a completion widget and may be changed there.
is unset or empty they will never be listed; if its value begins with
tt(list), they will always be listed; if it begins with tt(autolist)
or tt(ambiguous), they will be listed when the tt(AUTO_LIST) or
tt(LIST_AMBIGUOUS) options respectively would normally cause them to
be. Finally, if the value contains the string tt(explanations), only
the explanation strings, if any, will be listed. It will be set
appropriately on entry to a completion widget and may be changed
there.
)
item(tt(force_list))(
If the value for the tt(list) key is tt(autolist) or tt(ambiguous), the list will
@ -233,6 +239,13 @@ Initially this is set to the value of the tt(LISTMAX) parameter.
It may be set to any other numeric value; when the widget exits this value
will be used in the same way as the value of tt(LISTMAX).
)
item(tt(list_lines))(
This gives the number of lines that are needed to display the full
list of completions. Note that to calculate the total number of lines
to display you need to add the number of lines needed for the command
line to this value, this is available as the value of the tt(BLINES)
special parameter.
)
item(tt(last_prompt))(
If this is set to an non-empty string, the completion code will move
the cursor back to the previous prompt after the list of completions

View file

@ -141,6 +141,12 @@ The part of the buffer that lies to the right of the cursor position.
If it is assigned to, only that part of the buffer is replaced, and the
cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
)
vindex(BLINES)
item(tt(BLINES))(
The number of screen lines needed for the edit buffer currently
displayed on screen (i.e. without any changes to the preceding
parameters done after the last redisplay).
)
vindex(PREBUFFER)
item(tt(PREBUFFER) (scalar))(
In a multi-line input at the secondary prompt, this read-only parameter

View file

@ -1,8 +1,7 @@
# incremental-complete-word() {
# Autoload this function, run `zle -N <func-name>' and bind <func-name>
# to a key.
# This allows incremental completion of a word. After starting this
# command, a list of completion choices can be shown after every character
# you type, which you can delete with ^h or DEL. RET will accept the
@ -23,10 +22,12 @@
# such a common prefix, respectively. The sequence `%c' is replaced
# by the name of the completer function that generated the matches
# (without the leading underscore). Finally, `%n' is replaced by the
# number of matches generated and `%a' is replaced by an empty string
# number of matches generated, `%a' is replaced by an empty string
# if the matches are in the normal set (i.e. the one without file names
# with one of the suffixes from `fignore') and with ` -alt-' if the
# matches are in the alternate set.
# matches are in the alternate set, and if the `incremental_list' key
# (see below) is set, `%l' is replaced by `...' if the list of matches
# is too long to fit on the screen and with an empty string otherwise.
#
# incremental_stop
# Pattern matching keys which will cause icompletion to stop and the
@ -44,68 +45,37 @@
# key-press.
emulate -L zsh
unsetopt autolist menucomplete automenu # doesn't work well
# The main widget function.
local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word
local lastl lastr wid twid num alt
incremental-complete-word() {
emulate -L zsh
unsetopt autolist menucomplete automenu # doesn't work well
[[ -n "$compconfig[incremental_completer]" ]] &&
set ${(s.:.)compconfig[incremental_completer]}
pmpt="${compconfig[incremental_prompt]-incremental (%c): %u%s}"
local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word
local lastl lastr wid twid num alt post toolong
if [[ -n "$compconfig[incremental_list]" ]]; then
wid=list-choices
else
wid=complete-word
fi
[[ -n "$compconfig[incremental_completer]" ]] &&
set ${(s.:.)compconfig[incremental_completer]}
pmpt="${compconfig[incremental_prompt]-incremental (%c): %u%s %l}"
zle $wid "$@"
LBUFFER="$lbuf"
RBUFFER="$rbuf"
if (( ! _lastcomp[nmatches] )); then
word=''
state='-no match-'
elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
word=''
state='-no prefix-'
else
word="${_lastcomp[unambiguous]}"
state=''
fi
num=$_lastcomp[normal_nmatches]
if (( ! num )); then
num="${_lastcomp[nmatches]}"
alt=' -alt-'
fi
zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}"
read -k key
while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
'#key' -ne '#\\C-g' ]]; do
twid=$wid
if [[ "$key" = ${~compconfig[incremental_stop]} ]]; then
zle -U "$key"
return
elif [[ "$key" = ${~compconfig[incremental_break]} ]]; then
return
elif [[ '#key' -eq '#\\C-h' || '#key' -eq '#\\C-?' ]]; then
[[ $#LBUFFER -gt $#l ]] && LBUFFER="$LBUFFER[1,-2]"
elif [[ '#key' -eq '#\\t' ]]; then
zle complete-word "$@"
lbuf="$LBUFFER"
rbuf="$RBUFFER"
elif [[ '#key' -eq '#\\C-d' ]]; then
twid=list-choices
if [[ -n "$compconfig[incremental_list]" ]]; then
wid=list-choices
post=( icw-list-helper )
else
LBUFFER="$LBUFFER$key"
wid=complete-word
post=()
fi
lastl="$LBUFFER"
lastr="$RBUFFER"
zle $twid "$@"
LBUFFER="$lastl"
RBUFFER="$lastr"
if (( ! _lastcomp[nmatches] )); then
comppostfuncs=( "$post[@]" )
zle $wid "$@"
LBUFFER="$lbuf"
RBUFFER="$rbuf"
num=$_lastcomp[nmatches]
if (( ! num )); then
num="${_lastcomp[alternate_nmatches]}"
alt=' -alt-'
fi
if (( ! num )); then
word=''
state='-no match-'
elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
@ -115,20 +85,78 @@ while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
word="${_lastcomp[unambiguous]}"
state=''
fi
num=$_lastcomp[normal_nmatches]
if (( ! num )); then
num="${_lastcomp[nmatches]}"
alt=' -alt-'
else
alt=''
fi
zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}"
zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}"
read -k key
done
if [[ '#key' -eq '#\\C-g' ]]; then
LBUFFER="$lbuf"
RBUFFER="$rbuf"
fi
zle -Rc
# }
while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
'#key' -ne '#\\C-g' ]]; do
twid=$wid
if [[ "$key" = ${~compconfig[incremental_stop]} ]]; then
zle -U "$key"
return
elif [[ "$key" = ${~compconfig[incremental_break]} ]]; then
return
elif [[ '#key' -eq '#\\C-h' || '#key' -eq '#\\C-?' ]]; then
[[ $#LBUFFER -gt $#l ]] && LBUFFER="$LBUFFER[1,-2]"
elif [[ '#key' -eq '#\\t' ]]; then
zle complete-word "$@"
lbuf="$LBUFFER"
rbuf="$RBUFFER"
elif [[ '#key' -eq '#\\C-d' ]]; then
twid=list-choices
else
LBUFFER="$LBUFFER$key"
fi
lastl="$LBUFFER"
lastr="$RBUFFER"
[[ "$twid" = "$wid" ]] && comppostfuncs=( "$post[@]" )
toolong=''
zle $twid "$@"
LBUFFER="$lastl"
RBUFFER="$lastr"
num=$_lastcomp[nmatches]
if (( ! num )); then
num="${_lastcomp[alternate_nmatches]}"
alt=' -alt-'
else
alt=''
fi
if (( ! num )); then
word=''
state='-no match-'
elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
word=''
state='-no prefix-'
else
word="${_lastcomp[unambiguous]}"
state=''
fi
zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}"
read -k key
done
if [[ '#key' -eq '#\\C-g' ]]; then
LBUFFER="$lbuf"
RBUFFER="$rbuf"
fi
zle -Rc
}
# Helper function used as a completion post-function used to make sure that
# the list of matches in only shown if it fits on the screen.
icw-list-helper() {
# +1 for the status line we will add...
if [[ compstate[list_lines]+BUFFERLINES+1 -gt LINES ]]; then
compstate[list]='list explanations'
if [[ compstate[list_lines]+BUFFERLINES+1 -gt LINES ]]; then
compstate[list]=''
compstate[force_list]=yes
fi
toolong='...'
fi
}
incremental-complete-word "$@"

View file

@ -350,6 +350,7 @@ struct cldata {
int nlist; /* number of matches to list */
int nlines; /* number of lines needed */
int hidden; /* != 0 if there are hidden matches */
int onlyexpl; /* != 0 if only explanations to print */
};
typedef void (*CLPrintFunc)(Cmgroup, Cmatch *, int, int, int, int,
@ -440,8 +441,10 @@ struct chdata {
#define CP_OLDINS (1 << CPN_OLDINS)
#define CPN_VARED 24
#define CP_VARED (1 << CPN_VARED)
#define CPN_NNMATCHES 25
#define CP_NNMATCHES (1 << CPN_NNMATCHES)
#define CPN_ANMATCHES 25
#define CP_ANMATCHES (1 << CPN_ANMATCHES)
#define CPN_LISTLINES 26
#define CP_LISTLINES (1 << CPN_LISTLINES)
#define CP_KEYPARAMS 26
#define CP_ALLKEYS ((unsigned int) 0xffffff)
#define CP_KEYPARAMS 27
#define CP_ALLKEYS ((unsigned int) 0x7ffffff)

View file

@ -66,6 +66,15 @@ int (*makecomplistcallptr) _((Compctl));
/**/
int (*makecomplistctlptr) _((int));
/**/
zlong (*num_matchesptr) _((int));
/**/
zlong (*list_linesptr) _((void));
/**/
void (*comp_listptr) _((char *));
/**/
char *(*unambig_dataptr) _((int *));
@ -104,11 +113,10 @@ int incompfunc;
/**/
zlong compcurrent,
compnmatches,
compnnmatches,
compmatcher,
compmatchertot,
complistmax;
complistmax,
complistlines;
/**/
char **compwords,

View file

@ -2249,7 +2249,7 @@ static struct compparam comprparams[] = {
};
static struct compparam compkparams[] = {
{ "nmatches", PM_INTEGER, VAL(compnmatches), NULL, NULL },
{ "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 },
@ -2259,7 +2259,7 @@ static struct compparam compkparams[] = {
{ "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL, NULL },
{ "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL, NULL },
{ "restore", PM_SCALAR, VAL(comprestore), NULL, NULL },
{ "list", PM_SCALAR, VAL(complist), NULL, NULL },
{ "list", PM_SCALAR, NULL, VAL(set_complist), VAL(get_complist) },
{ "force_list", PM_SCALAR, VAL(compforcelist), NULL, NULL },
{ "insert", PM_SCALAR, VAL(compinsert), NULL, NULL },
{ "exact", PM_SCALAR, VAL(compexact), NULL, NULL },
@ -2275,7 +2275,8 @@ static struct compparam compkparams[] = {
{ "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL },
{ "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL },
{ "vared", PM_SCALAR, VAL(compvared), NULL, NULL },
{ "normal_nmatches", PM_INTEGER, VAL(compnnmatches), NULL, NULL },
{ "alternate_nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_anmatches) },
{ "list_lines", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_listlines) },
{ NULL, 0, NULL, NULL, NULL }
};
@ -2382,6 +2383,41 @@ set_compstate(Param pm, HashTable ht)
deleteparamtable(ht);
}
/**/
static zlong
get_nmatches(Param pm)
{
return num_matchesptr(1);
}
/**/
static zlong
get_anmatches(Param pm)
{
return num_matchesptr(0);
}
/**/
static zlong
get_listlines(Param pm)
{
return list_linesptr();
}
/**/
static void
set_complist(Param pm, char *v)
{
comp_listptr(v);
}
/**/
static char *
get_complist(Param pm)
{
return complist;
}
/**/
static char *
get_unambig(Param pm)

View file

@ -525,9 +525,9 @@ struct menustack {
char *line;
char *brbeg;
char *brend;
int cs, acc;
int cs, acc, nmatches;
struct menuinfo info;
Cmgroup amatches, pmatches, lmatches;
Cmgroup amatches, pmatches, lastmatches, lastlmatches;
};
static int
@ -538,7 +538,7 @@ domenuselect(Hookdef dummy, Chdata dat)
Cmgroup *pg;
Thingy cmd;
Menustack u = NULL;
int i = 0, acc = 0, wishcol = 0, setwish = 0;
int i = 0, acc = 0, wishcol = 0, setwish = 0, oe = onlyexpl;
char *s;
HEAPALLOC {
@ -555,6 +555,7 @@ domenuselect(Hookdef dummy, Chdata dat)
noselect = 0;
mselect = (*(minfo.cur))->gnum;
for (;;) {
onlyexpl = 0;
showinglist = -2;
zrefresh();
inselect = 1;
@ -601,18 +602,23 @@ domenuselect(Hookdef dummy, Chdata dat)
memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
s->amatches = amatches;
s->pmatches = pmatches;
s->lmatches = lmatches;
s->lastmatches = lastmatches;
s->lastlmatches = lastlmatches;
s->acc = menuacc;
s->brbeg = dupstring(brbeg);
s->brend = dupstring(brend);
s->nmatches = nmatches;
menucmp = menuacc = 0;
fixsuffix();
validlist = 0;
pmatches = NULL;
amatches = pmatches = lastmatches = NULL;
invalidatelist();
menucomplete(zlenoargs);
PERMALLOC {
menucomplete(zlenoargs);
} LASTALLOC;
if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) {
noselect = clearlist = listshown = 1;
onlyexpl = 0;
zrefresh();
break;
}
@ -629,10 +635,12 @@ domenuselect(Hookdef dummy, Chdata dat)
s->line = dupstring((char *) line);
s->cs = cs;
memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
s->amatches = s->pmatches = s->lmatches = NULL;
s->amatches = s->pmatches =
s->lastmatches = s->lastlmatches = NULL;
s->acc = menuacc;
s->brbeg = dupstring(brbeg);
s->brend = dupstring(brend);
s->nmatches = nmatches;
acceptlast();
do_menucmp(0);
mselect = (*(minfo.cur))->gnum;
@ -652,12 +660,15 @@ domenuselect(Hookdef dummy, Chdata dat)
menuacc = u->acc;
memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
p = &(minfo.cur);
if (u->pmatches && pmatches != u->pmatches) {
freematches();
if (u->lastmatches && lastmatches != u->lastmatches) {
if (lastmatches)
freematches(lastmatches);
amatches = u->amatches;
pmatches = u->pmatches;
lmatches = u->lmatches;
hasperm = 1;
lastmatches = u->lastmatches;
lastlmatches = u->lastlmatches;
nmatches = u->nmatches;
hasoldlist = 1;
}
zsfree(brbeg);
zsfree(brend);
@ -666,6 +677,7 @@ domenuselect(Hookdef dummy, Chdata dat)
u = u->prev;
clearlist = 1;
setwish = 1;
listdat.valid = 0;
} else if (cmd == Th(z_redisplay)) {
redisplay(zlenoargs);
continue;
@ -819,19 +831,11 @@ domenuselect(Hookdef dummy, Chdata dat)
do_single(**p);
mselect = (**p)->gnum;
}
if (u) {
int hp = hasperm;
Cmgroup m = pmatches;
if (u)
for (; u; u = u->prev)
if (u->lastmatches != lastmatches)
freematches(u->lastmatches);
for (; u; u = u->prev) {
if (u->pmatches != m) {
pmatches = u->pmatches;
freematches();
}
}
pmatches = m;
hasperm = hp;
}
selectlocalmap(NULL);
mselect = -1;
inselect = 0;
@ -842,6 +846,7 @@ domenuselect(Hookdef dummy, Chdata dat)
}
if (!noselect) {
showinglist = -2;
onlyexpl = oe;
zrefresh();
}
fdat = NULL;

View file

@ -979,6 +979,9 @@ setup_zle(Module m)
getcpatptr = getcpat;
makecomplistcallptr = makecomplistcall;
makecomplistctlptr = makecomplistctl;
num_matchesptr = num_matches;
list_linesptr = list_lines;
comp_listptr = comp_list;
unambig_dataptr = unambig_data;
set_comp_sepptr = set_comp_sep;
@ -1059,6 +1062,9 @@ finish_zle(Module m)
getcpatptr = NULL;
makecomplistcallptr = NULL;
makecomplistctlptr = NULL;
num_matchesptr = NULL;
list_linesptr = NULL;
comp_listptr = NULL;
unambig_dataptr = NULL;
set_comp_sepptr = NULL;

View file

@ -73,6 +73,8 @@ static struct zleparam {
unset_numeric, NULL },
{ "HISTNO", PM_INTEGER | PM_READONLY, NULL, FN(get_histno),
zleunsetfn, NULL },
{ "BUFFERLINES", PM_INTEGER | PM_READONLY, NULL, FN(get_bufferlines),
zleunsetfn, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL }
};
@ -285,3 +287,10 @@ get_histno(Param pm)
{
return histline;
}
/**/
static zlong
get_bufferlines(Param pm)
{
return nlnct;
}

View file

@ -136,16 +136,24 @@ static int brpl, brsl, brpcs, brscs, qbrpl, qbrsl, hasunqu;
static LinkList matches, fmatches;
/* This holds the list of matches-groups. lmatches is a pointer to the *
* last element in this list. */
/* This holds the list of matches-groups. lastmatches holds the last list of
* permanently allocated matches, pmatches is the same for the list
* currently built, amatches is the heap allocated stuff during completion
* (after all matches have been generated it is an alias for pmatches), and
* lmatches/lastlmatches is a pointer to the last element in the lists. */
/**/
Cmgroup pmatches, amatches, lmatches;
Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches;
/* Non-zero if we have permanently allocated matches. */
/* Non-zero if we have permanently allocated matches (old and new). */
/**/
int hasperm;
int hasoldlist, hasperm;
/* Non-zero if we have newly added matches. */
/**/
int newmatches;
/* Number of permanently allocated matches and groups. */
@ -153,13 +161,19 @@ static int permmnum, permgnum;
/* The total number of matches and the number of matches to be listed. */
static int nmatches, smatches;
/**/
int nmatches, smatches;
/* !=0 if we have a valid completion list. */
/**/
int validlist;
/* != 0 if only explanation strings should be printed */
/**/
int onlyexpl;
/* Information about the matches for listing. */
/**/
@ -234,7 +248,7 @@ static Cmgroup mgroup;
/* Match counters: all matches, normal matches (not alternate set). */
static int mnum, nmnum;
static int mnum;
/* The match counter when unambig_data() was called. */
@ -3899,8 +3913,6 @@ add_match_data(int alt, char *str, Cline line,
ai->line = join_clines(ai->line, line);
mnum++;
if (!alt)
nmnum++;
ai->count++;
/* Allocate and fill the match structure. */
@ -3929,6 +3941,8 @@ add_match_data(int alt, char *str, Cline line,
cm->rems = cm->remf = cm->disp = NULL;
addlinknode((alt ? fmatches : matches), cm);
newmatches = 1;
/* One more match for this explanation. */
if (expl) {
if (alt)
@ -4283,8 +4297,6 @@ addmatches(Cadata dat, char **argv)
free_cline(lc);
}
}
compnmatches = mnum;
compnnmatches = nmnum;
if (dat->apar)
set_list_array(dat->apar, aparl);
if (dat->opar)
@ -4843,13 +4855,18 @@ docompletion(char *s, int lst, int incmd)
minfo.cur = NULL;
minfo.asked = 0;
do_single(m->matches[0]);
if (compforcelist && *compforcelist && uselist)
showinglist = -2;
else
if (compforcelist && *compforcelist) {
if (uselist)
showinglist = -2;
else
clearlist = 1;
} else
invalidatelist();
}
} else {
invalidatelist();
if (compforcelist && *compforcelist)
clearlist = 1;
cs = 0;
foredel(ll);
inststr(origline);
@ -4858,6 +4875,9 @@ docompletion(char *s, int lst, int incmd)
/* Print the explanation strings if needed. */
if (!showinglist && validlist && usemenu != 2 && nmatches != 1 &&
useline != 2 && (!oldlist || !listshown)) {
onlyexpl = 1;
showinglist = -2;
#if 0
Cmgroup g = amatches;
Cexpl *e;
int up = 0, tr = 1, nn = 0;
@ -4894,6 +4914,7 @@ docompletion(char *s, int lst, int incmd)
putc('\n', shout);
fflush(shout);
}
#endif
}
compend:
for (n = firstnode(matchers); n; incnode(n))
@ -5067,8 +5088,6 @@ callcompfunc(char *s, char *fn)
zsfree(compqisuffix);
compqisuffix = ztrdup(qisuf ? qisuf : "");
compcurrent = (usea ? (clwpos + 1 - aadd) : 0);
compnmatches = mnum;
compnnmatches = nmnum;
zsfree(complist);
switch (uselist) {
@ -5103,7 +5122,7 @@ callcompfunc(char *s, char *fn)
comptoend = ztrdup("match");
zsfree(compoldlist);
zsfree(compoldins);
if (hasperm && permmnum) {
if (hasoldlist && permmnum) {
if (listshown)
compoldlist = "shown";
else
@ -5150,14 +5169,17 @@ callcompfunc(char *s, char *fn)
if (!complist)
uselist = 0;
else if (!strcmp(complist, "list"))
else if (!strncmp(complist, "list", 4))
uselist = 1;
else if (!strcmp(complist, "auto") || !strcmp(complist, "autolist"))
else if (!strncmp(complist, "auto", 4))
uselist = 2;
else if (!strcmp(complist, "ambig") || !strcmp(complist, "ambiguous"))
else if (!strncmp(complist, "ambig", 5))
uselist = 3;
else
uselist = 0;
onlyexpl = (complist && strstr(complist, "expl"));
if (!compinsert)
useline = 0;
else if (!strcmp(compinsert, "unambig") ||
@ -5193,8 +5215,8 @@ callcompfunc(char *s, char *fn)
else
movetoend = 2;
oldlist = (hasperm && compoldlist && !strcmp(compoldlist, "keep"));
oldins = (hasperm && minfo.cur &&
oldlist = (hasoldlist && compoldlist && !strcmp(compoldlist, "keep"));
oldins = (hasoldlist && minfo.cur &&
compoldins && !strcmp(compoldins, "keep"));
zfree(comprpms, CP_REALPARAMS * sizeof(Param));
@ -5287,13 +5309,13 @@ makecomplist(char *s, int incmd, int lst)
if (!validlist)
lastambig = 0;
amatches = NULL;
mnum = nmnum = 0;
mnum = 0;
unambig_mnum = -1;
isuf = NULL;
insmnum = insgnum = 1;
insgroup = oldlist = oldins = 0;
begcmgroup("default", 0);
menucmp = menuacc = 0;
menucmp = menuacc = newmatches = onlyexpl = 0;
ccused = newlinklist();
ccstack = newlinklist();
@ -5318,16 +5340,32 @@ makecomplist(char *s, int incmd, int lst)
if (oldlist) {
nmatches = onm;
validlist = 1;
amatches = pmatches;
amatches = lastmatches;
lmatches = lastlmatches;
if (pmatches) {
freematches(pmatches);
pmatches = NULL;
hasperm = 0;
}
redup(osi, 0);
return 0;
}
PERMALLOC {
permmatches();
if (lastmatches) {
freematches(lastmatches);
lastmatches = NULL;
}
permmatches(1);
amatches = pmatches;
} LASTALLOC;
lastmatches = pmatches;
lastlmatches = lmatches;
pmatches = NULL;
hasperm = 0;
hasoldlist = 1;
if (nmatches && !errflag) {
validlist = 1;
@ -5709,8 +5747,6 @@ makecomplistcall(Compctl cc)
instring = ois;
inbackt = oib;
autoq = oaq;
compnmatches = mnum;
compnnmatches = nmnum;
} LASTALLOC;
} SWITCHBACKHEAPS;
@ -5785,8 +5821,6 @@ makecomplistctl(int flags)
inbackt = oib;
autoq = oaq;
offs = ooffs;
compnmatches = mnum;
compnnmatches = nmnum;
zsfree(cmdstr);
freearray(clwords);
cmdstr = os;
@ -7145,8 +7179,11 @@ invalidatelist(void)
{
if (showinglist == -2)
listmatches();
if (validlist)
freematches();
if (validlist) {
freematches(lastmatches);
lastmatches = NULL;
hasoldlist = 0;
}
lastambig = menucmp = menuacc = validlist = showinglist = fromcomp = 0;
listdat.valid = 0;
if (listshown < 0)
@ -7463,6 +7500,7 @@ addexpl(void)
}
}
addlinknode(expls, expl);
newmatches = 1;
}
/* This duplicates one match. */
@ -7500,32 +7538,42 @@ dupmatch(Cmatch m)
/* This duplicates all groups of matches. */
/**/
static void
permmatches(void)
static int
permmatches(int last)
{
Cmgroup g = amatches, n;
Cmatch *p, *q;
Cexpl *ep, *eq, e, o;
Compctl *cp, *cq;
int nn, nl, ll, fi = 0, gn = 1, mn = 1, rn;
LinkList mlist;
static int fi = 0;
int nn, nl, ll, gn = 1, mn = 1, rn;
if (hasperm)
freematches();
if (pmatches && !newmatches)
return fi;
amatches = lmatches = NULL;
newmatches = fi = 0;
if (pmatches)
freematches(pmatches);
pmatches = lmatches = NULL;
nmatches = smatches = 0;
if (!ainfo->count) {
ainfo = fainfo;
if (last)
ainfo = fainfo;
fi = 1;
}
while (g) {
HEAPALLOC {
if (empty(g->lmatches))
/* We have no matches, try ignoring fignore. */
g->lmatches = g->lfmatches;
mlist = g->lfmatches;
else
mlist = g->lmatches;
g->matches = makearray(g->lmatches, 1, g->flags, &nn, &nl, &ll);
g->matches = makearray(mlist, 1, g->flags, &nn, &nl, &ll);
g->mcount = nn;
if ((g->lcount = nn - nl) < 0)
g->lcount = 0;
@ -7548,10 +7596,10 @@ permmatches(void)
if (!lmatches)
lmatches = n;
if (amatches)
amatches->prev = n;
n->next = amatches;
amatches = n;
if (pmatches)
pmatches->prev = n;
n->next = pmatches;
pmatches = n;
n->prev = 0;
n->num = gn++;
@ -7594,18 +7642,71 @@ permmatches(void)
g = g->next;
}
for (g = amatches; g; g = g->next) {
for (g = pmatches; g; g = g->next) {
for (rn = 1, q = g->matches; *q; q++) {
(*q)->rnum = rn++;
(*q)->gnum = mn++;
}
}
pmatches = amatches;
hasperm = 1;
permmnum = mn - 1;
permgnum = gn - 1;
return fi;
}
/* Return the real number of matches. */
/**/
zlong
num_matches(int normal)
{
int alt;
PERMALLOC {
alt = permmatches(0);
} LASTALLOC;
if (normal)
return (alt ? 0 : nmatches);
else
return (alt ? nmatches : 0);
}
/* Return the number of screen lines needed for the list. */
/**/
zlong
list_lines(void)
{
Cmgroup oam;
PERMALLOC {
permmatches(0);
} LASTALLOC;
oam = amatches;
amatches = pmatches;
listdat.valid = 0;
calclist();
listdat.valid = 0;
amatches = oam;
return listdat.nlines;
}
/**/
void
comp_list(char *v)
{
zsfree(complist);
complist = ztrdup(v);
onlyexpl = (v && strstr(v, "expl"));
}
/**/
/* This frees one match. */
/**/
@ -7634,9 +7735,9 @@ freematch(Cmatch m)
/**/
void
freematches(void)
freematches(Cmgroup g)
{
Cmgroup g = pmatches, n;
Cmgroup n;
Cmatch *m;
Cexpl *e;
Compctl *c;
@ -7670,8 +7771,6 @@ freematches(void)
g = n;
}
hasperm = 0;
listdat.valid = 0;
}
/* Insert the given string into the command line. If move is non-zero, *
@ -8576,27 +8675,33 @@ printfmt(char *fmt, int n, int dopr, int doesc)
break;
case 'B':
b = 1;
tcout(TCBOLDFACEBEG);
if (dopr)
tcout(TCBOLDFACEBEG);
break;
case 'b':
b = 0; m = 1;
tcout(TCALLATTRSOFF);
if (dopr)
tcout(TCALLATTRSOFF);
break;
case 'S':
s = 1;
tcout(TCSTANDOUTBEG);
if (dopr)
tcout(TCSTANDOUTBEG);
break;
case 's':
s = 0; m = 1;
tcout(TCSTANDOUTEND);
if (dopr)
tcout(TCSTANDOUTEND);
break;
case 'U':
u = 1;
tcout(TCUNDERLINEBEG);
if (dopr)
tcout(TCUNDERLINEBEG);
break;
case 'u':
u = 0; m = 1;
tcout(TCUNDERLINEEND);
if (dopr)
tcout(TCUNDERLINEEND);
break;
case '{':
for (p++; *p && (*p != '%' || p[1] != '}'); p++, cc++)
@ -8608,7 +8713,7 @@ printfmt(char *fmt, int n, int dopr, int doesc)
p--;
break;
}
if (m) {
if (dopr && m) {
if (b)
tcout(TCBOLDFACEBEG);
if (s)
@ -8697,7 +8802,8 @@ calclist(void)
int max = 0, i;
VARARR(int, mlens, nmatches + 1);
if (listdat.valid && menuacc == listdat.menuacc &&
if (listdat.valid && onlyexpl == listdat.onlyexpl &&
menuacc == listdat.menuacc &&
lines == listdat.lines && columns == listdat.columns)
return;
@ -8705,7 +8811,7 @@ calclist(void)
char **pp = g->ylist;
int nl = 0, l, glong = 1, gshort = columns, ndisp = 0, totl = 0;
if (pp) {
if (!onlyexpl && pp) {
/* We have an ylist, lets see, if it contains newlines. */
hidden = 1;
while (!nl && *pp)
@ -8742,7 +8848,7 @@ calclist(void)
pp++;
}
}
} else {
} else if (!onlyexpl) {
for (p = g->matches; (m = *p); p++) {
if (menuacc && !hasbrpsfx(m, minfo.prebr, minfo.postbr)) {
m->flags |= CMF_HIDE;
@ -8798,50 +8904,52 @@ calclist(void)
max = i;
}
}
for (g = amatches; g; g = g->next) {
char **pp;
int glines = 0;
if (!onlyexpl) {
for (g = amatches; g; g = g->next) {
char **pp;
int glines = 0;
zfree(g->widths, 0);
g->widths = NULL;
zfree(g->widths, 0);
g->widths = NULL;
if ((pp = g->ylist)) {
if (!(g->flags & CGF_LINES)) {
if ((pp = g->ylist)) {
if (!(g->flags & CGF_LINES)) {
if (g->cols) {
glines += (arrlen(pp) + g->cols - 1) / g->cols;
if (g->cols > 1)
g->width += (max - (g->width * g->cols - add)) / g->cols;
} else {
g->cols = 1;
g->width = 1;
while (*pp)
glines += 1 + (strlen(*pp++) / columns);
}
}
} else {
if (g->cols) {
glines += (arrlen(pp) + g->cols - 1) / g->cols;
glines += (g->dcount + g->cols - 1) / g->cols;
if (g->cols > 1)
g->width += (max - (g->width * g->cols - add)) / g->cols;
} else {
} else if (!(g->flags & CGF_LINES)) {
g->cols = 1;
g->width = 1;
while (*pp)
glines += 1 + (strlen(*pp++) / columns);
g->width = 0;
for (p = g->matches; (m = *p); p++)
if (!(m->flags & CMF_HIDE)) {
if (m->disp) {
if (!(m->flags & CMF_DISPLINE))
glines += 1 + (mlens[m->gnum] / columns);
} else if (!(m->flags & CMF_NOLIST))
glines += 1 + ((1 + mlens[m->gnum]) / columns);
}
}
}
} else {
if (g->cols) {
glines += (g->dcount + g->cols - 1) / g->cols;
if (g->cols > 1)
g->width += (max - (g->width * g->cols - add)) / g->cols;
} else if (!(g->flags & CGF_LINES)) {
g->cols = 1;
g->width = 0;
for (p = g->matches; (m = *p); p++)
if (!(m->flags & CMF_HIDE)) {
if (m->disp) {
if (!(m->flags & CMF_DISPLINE))
glines += 1 + (mlens[m->gnum] / columns);
} else if (!(m->flags & CMF_NOLIST))
glines += 1 + ((1 + mlens[m->gnum]) / columns);
}
}
g->lins = glines;
nlines += glines;
}
g->lins = glines;
nlines += glines;
}
if (isset(LISTPACKED)) {
if (!onlyexpl && isset(LISTPACKED)) {
char **pp;
int *ws, tlines, tline, tcols, maxlen, nth, width;
@ -9017,6 +9125,9 @@ calclist(void)
listdat.nlist = nlist;
listdat.nlines = nlines;
listdat.menuacc = menuacc;
listdat.onlyexpl = onlyexpl;
listdat.columns = columns;
listdat.lines = lines;
}
/**/
@ -9111,7 +9222,7 @@ printlist(int over, CLPrintFunc printm)
e++;
}
}
if (pp && *pp) {
if (!listdat.onlyexpl && pp && *pp) {
if (pnl) {
putc('\n', shout);
pnl = 0;
@ -9164,7 +9275,7 @@ printlist(int over, CLPrintFunc printm)
pp += (isset(LISTROWSFIRST) ? g->cols : 1);
}
}
} else if (g->lcount) {
} else if (!listdat.onlyexpl && g->lcount) {
int n = g->dcount, nl, nc, i, j, wid;
Cmatch *q;
@ -9329,7 +9440,7 @@ int
listlist(LinkList l)
{
struct cmgroup dg;
int vl = validlist, sm = smatches;
int vl = validlist, sm = smatches, nm = nmatches;
char *oclp = complastprompt;
Cmgroup am = amatches;
@ -9341,12 +9452,14 @@ listlist(LinkList l)
validlist = 1;
memset(&dg, 0, sizeof(struct cmgroup));
dg.ylist = (char **) makearray(l, 0, 1, &(dg.lcount), NULL, NULL);
nmatches = dg.lcount;
amatches = &dg;
ilistmatches(NULL, NULL);
amatches = am;
validlist = vl;
smatches = sm;
nmatches = nm;
complastprompt = oclp;
return !dg.lcount;