1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-13 01:31:18 +02:00

two new modes for menu selection: incremental search and interactive (17366)

This commit is contained in:
Sven Wischnowsky 2002-06-26 11:07:42 +00:00
parent 03105a5d6e
commit d28f67623f
8 changed files with 502 additions and 47 deletions

View file

@ -1,3 +1,11 @@
2002-06-26 Sven Wischnowsky <wischnow@zsh.org>
* 17366: Completion/Base/Core/_main_complete,
Completion/Zsh/Command/_zstyle, Doc/Zsh/compsys.yo,
Doc/Zsh/mod_complist.yo, Src/Zle/compcore.c, Src/Zle/complist.c,
Src/Zle/compresult.c: two new modes for menu selection:
incremental search and interactive
2002-06-24 Peter Stephenson <pws@csr.com> 2002-06-24 Peter Stephenson <pws@csr.com>
* 17361: Src/zle_hist.c: Be safer about NULL returns from * 17361: Src/zle_hist.c: Be safer about NULL returns from

View file

@ -267,6 +267,19 @@ if [[ $compstate[old_list] = keep || nm -gt 1 ]]; then
unset MENUSELECT unset MENUSELECT
fi fi
fi fi
if [[ -n "$MENUSELECT" ]]; then
if [[ -n "$_menu_style[(r)interactive*]" ]]; then
MENUMODE=interactive
elif [[ -n "$_menu_style[(r)search*]" ]]; then
if [[ -n "$_menu_style[(r)*backward*]" ]]; then
MENUMODE=search-backward
else
MENUMODE=search-forward
fi
else
unset MENUMODE
fi
fi
fi fi
elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then
compstate[insert]='' compstate[insert]=''

View file

@ -206,7 +206,8 @@ while (( $#state )); do
;; ;;
boolauto) boolauto)
_wanted values expl boolean compadd true false auto select _wanted values expl boolean \
compadd true false auto select search search-backward interactive
;; ;;
cmdorcont) cmdorcont)

View file

@ -1824,6 +1824,13 @@ To turn on menu completion or menu selection when a certain number of
matches is generated em(or) the list of matches does not fit onto the matches is generated em(or) the list of matches does not fit onto the
screen, both of `tt(yes=)' and `tt(select=)' can be given twice, once screen, both of `tt(yes=)' and `tt(select=)' can be given twice, once
with a number and once with `tt(long)' or `tt(long-list)'. with a number and once with `tt(long)' or `tt(long-list)'.
Finally, the two special modes of menu selection, namely interactive
mode and incremental search can be pre-selected with this style. By
including the word `tt(interactive)' in the value, interactive mode
will be entered immediately when menu selection is started and the
string `tt(search)' does the same for incremental search. To select
backward incremental search, include the string `tt(search-backward)'.
) )
kindex(muttrc, completion style) kindex(muttrc, completion style)
item(tt(muttrc))( item(tt(muttrc))(

View file

@ -332,6 +332,22 @@ moves the mark to the next match
item(tt(reverse-menu-complete))( item(tt(reverse-menu-complete))(
moves the mark to the previous match moves the mark to the previous match
) )
item(tt(viinsert))(
this toggles between normal and interactive mode; in interactive mode
the keys bound to tt(self-insert) and tt(self-insert-unmeta) insert
into the command line as in normal editing mode but without leaving
menu selection; after each character completion is tried again and the
list changes to contain only the new matches; the completion widgets
make the longest unambiguous string be inserted in the command line
and tt(undo) and tt(backward-delete-char) go back to the previous set
of matches
)
item(tt(history-incremental-search-forward),
tt(history-incremental-search-backward))(
this starts incremental searches in the list of completions displayed;
in this mode, tt(accept-line) only leaves incremental search, going
back to the normal menu selection mode
)
enditem() enditem()
All movement functions wrap around at the edges; any other zle function not All movement functions wrap around at the edges; any other zle function not

View file

@ -360,7 +360,7 @@ do_completion(Hookdef dummy, Compldat dat)
haspattern = 1; haspattern = 1;
if (iforcemenu) { if (iforcemenu) {
if (nmatches) if (nmatches)
do_ambig_menu(); do_ambig_menu();
ret = !nmatches; ret = !nmatches;
} else if (useline < 0) } else if (useline < 0)
ret = selfinsert(zlenoargs); ret = selfinsert(zlenoargs);

View file

@ -400,8 +400,12 @@ static struct listcols mcolors;
/* Used in mtab/mgtab, for explanations. */ /* Used in mtab/mgtab, for explanations. */
#define mtexpl ((Cmatch *) 1) #define MMARK ((unsigned long) 1)
#define mgexpl ((Cmgroup) 1) #define mmarked(v) (((unsigned long) (v)) & MMARK)
#define mtmark(v) ((Cmatch *) (((unsigned long) (v)) | MMARK))
#define mtunmark(v) ((Cmatch *) (((unsigned long) (v)) & ~MMARK))
#define mgmark(v) ((Cmgroup) (((unsigned long) (v)) | MMARK))
#define mgunmark(v) ((Cmgroup) (((unsigned long) (v)) & ~MMARK))
/* Information for in-string colours. */ /* Information for in-string colours. */
@ -1065,8 +1069,8 @@ compprintlist(int showall)
int mm = (mcols * ml), i; int mm = (mcols * ml), i;
for (i = mcols; i--; ) { for (i = mcols; i--; ) {
mtab[mm + i] = mtexpl; mtab[mm + i] = mtmark(NULL);
mgtab[mm + i] = mgexpl; mgtab[mm + i] = mgmark(NULL);
} }
} }
if (stop) if (stop)
@ -1381,13 +1385,20 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width)
mlastm = m->gnum; mlastm = m->gnum;
if (m->disp && (m->flags & CMF_DISPLINE)) { if (m->disp && (m->flags & CMF_DISPLINE)) {
if (mselect >= 0 && !(m->flags & CMF_DUMMY)) { if (mselect >= 0) {
int mm = (mcols * ml), i; int mm = (mcols * ml), i;
for (i = mcols; i--; ) { if (m->flags & CMF_DUMMY) {
mtab[mm + i] = mp; for (i = mcols; i--; ) {
mgtab[mm + i] = g; mtab[mm + i] = mtmark(mp);
} mgtab[mm + i] = mgmark(g);
}
} else {
for (i = mcols; i--; ) {
mtab[mm + i] = mp;
mgtab[mm + i] = g;
}
}
} }
if (!dolist(ml)) { if (!dolist(ml)) {
mlprinted = printfmt(m->disp, 0, 0, 0) / columns; mlprinted = printfmt(m->disp, 0, 0, 0) / columns;
@ -1428,13 +1439,20 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width)
} else } else
mx = mc * g->width; mx = mc * g->width;
if (mselect >= 0 && !(m->flags & CMF_DUMMY)) { if (mselect >= 0) {
int mm = mcols * ml, i; int mm = mcols * ml, i;
for (i = (width ? width : mcols); i--; ) { if (m->flags & CMF_DUMMY) {
mtab[mx + mm + i] = mp; for (i = (width ? width : mcols); i--; ) {
mgtab[mx + mm + i] = g; mtab[mx + mm + i] = mtmark(mp);
} mgtab[mx + mm + i] = mgmark(g);
}
} else {
for (i = (width ? width : mcols); i--; ) {
mtab[mx + mm + i] = mp;
mgtab[mx + mm + i] = g;
}
}
} }
if (!dolist(ml)) { if (!dolist(ml)) {
mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns; mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
@ -1675,8 +1693,8 @@ adjust_mcol(int wish, Cmatch ***tabp, Cmgroup **grp)
tab -= mcol; tab -= mcol;
for (p = wish; p >= 0 && (!tab[p] || tab[p] == mtexpl); p--); for (p = wish; p >= 0 && (!tab[p] || mmarked(tab[p])); p--);
for (n = wish; n < mcols && (!tab[n] || tab[n] == mtexpl); n++); for (n = wish; n < mcols && (!tab[n] || mmarked(tab[n])); n++);
if (n == mcols) if (n == mcols)
n = -1; n = -1;
@ -1711,21 +1729,222 @@ struct menustack {
Cmgroup amatches, pmatches, lastmatches, lastlmatches; Cmgroup amatches, pmatches, lastmatches, lastlmatches;
char *origline; char *origline;
int origcs, origll; int origcs, origll;
char *status;
int mode;
}; };
typedef struct menusearch *Menusearch;
struct menusearch {
Menusearch prev;
char *str;
int line;
int col;
int back;
int state;
Cmatch **ptr;
};
#define MS_OK 0
#define MS_FAILED 1
#define MS_WRAPPED 2
#define MAX_STATUS 128
static char *
setmstatus(char *status, int *csp, int *llp, int *lenp)
{
char *p, *s, *ret = NULL;
int pl, sl, max;
if (csp) {
*csp = cs;
*llp = ll;
*lenp = lastend - wb;
ret = dupstring((char *) line);
p = (char *) zhalloc(cs - wb + 1);
strncpy(p, (char *) line + wb, cs - wb);
p[cs - wb] = '\0';
s = (char *) zhalloc(lastend - cs + 1);
strncpy(s, (char *) line + cs, lastend - cs);
s[lastend - cs] = '\0';
cs = wb;
foredel(lastend - wb);
pl = strlen(compprefix);
sl = strlen(compsuffix);
spaceinline(pl + sl);
strncpy(line + wb, compprefix, pl);
strncpy(line + wb + pl, compsuffix, sl);
cs = wb + pl;
} else {
p = compprefix;
s = compsuffix;
}
pl = strlen(p);
sl = strlen(s);
max = (columns < MAX_STATUS ? columns : MAX_STATUS) - 14;
if (max > 12) {
int h = (max - 2) >> 1;
strcpy(status, "interactive: ");
if (pl > h - 3) {
strcat(status, "...");
strcat(status, p + pl - h - 3);
} else
strcat(status, p);
strcat(status, "[]");
if (sl > h - 3) {
strncat(status, s, h - 3);
strcat(status, "...");
} else
strcat(status, s);
}
return ret;
}
static Menusearch msearchstack;
static char *msearchstr = NULL;
static int msearchstate;
static void
msearchpush(Cmatch **p, int back)
{
Menusearch s = (Menusearch) zhalloc(sizeof(struct menusearch));
s->prev = msearchstack;
msearchstack = s;
s->str = dupstring(msearchstr);
s->line = mline;
s->col = mcol;
s->back = back;
s->state = msearchstate;
s->ptr = p;
}
static Cmatch **
msearchpop(int *backp)
{
Menusearch s = msearchstack;
if (s->prev)
msearchstack = s->prev;
msearchstr = s->str;
mline = s->line;
mcol = s->col;
msearchstate = s->state;
*backp = s->back;
return s->ptr;
}
static Cmatch **
msearch(Cmatch **ptr, int ins, int back, int rep, int *wrapp)
{
char s[2];
Cmatch **p, *l = NULL, m;
int x = mcol, y = mline;
int ex, ey, wrap = 0, owrap = (msearchstate & MS_WRAPPED);
msearchpush(ptr, back);
if (ins) {
s[0] = c;
s[1] = '\0';
msearchstr = dyncat(msearchstr, s);
}
if (back) {
ex = mcols - 1;
ey = -1;
} else {
ex = 0;
ey = listdat.nlines;
}
p = mtab + (mline * mcols) + mcol;
if (rep)
l = *p;
while (1) {
if (!rep && mtunmark(*p) && *p != l) {
l = *p;
m = *mtunmark(*p);
if (strstr((m->disp ? m->disp : m->str), msearchstr)) {
mcol = x;
mline = y;
return p;
}
}
rep = 0;
if (back) {
p--;
if (--x < 0) {
x = mcols - 1;
y--;
}
} else {
p++;
if (++x == mcols) {
x = 0;
y++;
}
}
if (x == ex && y == ey) {
if (wrap) {
msearchstate = MS_FAILED | owrap;
break;
}
msearchstate |= MS_WRAPPED;
if (back) {
x = mcols - 1;
y = listdat.nlines - 1;
p = mtab + (y * mcols) + x;
} else {
x = y = 0;
p = mtab;
}
ex = mcol;
ey = mline;
wrap = 1;
*wrapp = 1;
}
}
return NULL;
}
#define MM_INTER 1
#define MM_FSEARCH 2
#define MM_BSEARCH 3
static int static int
domenuselect(Hookdef dummy, Chdata dat) domenuselect(Hookdef dummy, Chdata dat)
{ {
static Chdata fdat = NULL; static Chdata fdat = NULL;
static char *lastsearch = NULL;
Cmatch **p; Cmatch **p;
Cmgroup *pg; Cmgroup *pg;
Thingy cmd; Thingy cmd;
Menustack u = NULL; Menustack u = NULL;
int i = 0, acc = 0, wishcol = 0, setwish = 0, oe = onlyexpl, wasnext = 0; int i = 0, acc = 0, wishcol = 0, setwish = 0, oe = onlyexpl, wasnext = 0;
int space, lbeg = 0, step = 1, wrap, pl = nlnct, broken = 0, first = 1; int space, lbeg = 0, step = 1, wrap, pl = nlnct, broken = 0, first = 1;
int nolist = 0; int nolist = 0, mode = 0, modecs, modell, modelen;
char *s; char *s;
char status[MAX_STATUS], *modeline;
msearchstack = NULL;
msearchstr = "";
msearchstate = MS_OK;
status[0] = '\0';
queue_signals(); queue_signals();
if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) || if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
(dat && dat->num < atoi(s))))) { (dat && dat->num < atoi(s))))) {
@ -1744,6 +1963,21 @@ domenuselect(Hookdef dummy, Chdata dat)
if ((step += lines - nlnct) < 0) if ((step += lines - nlnct) < 0)
step = 1; step = 1;
} }
if ((s = getsparam("MENUMODE"))) {
if (!strcmp(s, "interactive")) {
int l = strlen(origline);
mode = MM_INTER;
cs = 0;
foredel(ll);
spaceinline(l);
strncpy((char *) line, origline, l);
cs = origcs;
setmstatus(status, NULL, NULL, NULL);
} else if (strpfx("search", s)) {
mode = (strstr(s, "back") ? MM_BSEARCH : MM_FSEARCH);
}
}
if ((mstatus = dupstring(getsparam("MENUPROMPT"))) && !*mstatus) if ((mstatus = dupstring(getsparam("MENUPROMPT"))) && !*mstatus)
mstatus = "%SScrolling active: current selection at %p%s"; mstatus = "%SScrolling active: current selection at %p%s";
unqueue_signals(); unqueue_signals();
@ -1770,7 +2004,7 @@ domenuselect(Hookdef dummy, Chdata dat)
for (y = 0; y < mlines; y++) { for (y = 0; y < mlines; y++) {
for (x = mcols; x; x--, p++) for (x = mcols; x; x--, p++)
if (*p && *p != mtexpl && **p && mselect == (**p)->gnum) if (*p && !mmarked(*p) && **p && mselect == (**p)->gnum)
break; break;
if (x) { if (x) {
mcol = mcols - x; mcol = mcols - x;
@ -1790,7 +2024,7 @@ domenuselect(Hookdef dummy, Chdata dat)
while (mlbeg) { while (mlbeg) {
for (q = p, c = columns; c; q++, c--) for (q = p, c = columns; c; q++, c--)
if (*q && *q != mtexpl) if (*q && !mmarked(*q))
break; break;
if (c) if (c)
break; break;
@ -1821,8 +2055,33 @@ domenuselect(Hookdef dummy, Chdata dat)
showinglist = -2; showinglist = -2;
if (first && !listshown && isset(LISTBEEP)) if (first && !listshown && isset(LISTBEEP))
zbeep(); zbeep();
if (first) {
modeline = dyncat(compprefix, compsuffix);
modecs = cs;
modell = ll;
modelen = minfo.len;
}
first = 0; first = 0;
if (mode == MM_INTER) {
statusline = status;
statusll = strlen(status);
} else if (mode) {
int l = sprintf(status, "%s%sisearch%s: ",
((msearchstate & MS_FAILED) ? "failed " : ""),
((msearchstate & MS_WRAPPED) ? "wrapped " : ""),
(mode == MM_FSEARCH ? "" : " backward"));
strncat(status, msearchstr, MAX_STATUS - l - 1);
statusline = status;
statusll = strlen(status);
} else {
statusline = NULL;
statusll = 0;
}
zrefresh(); zrefresh();
statusline = NULL;
statusll = 0;
inselect = 1; inselect = 1;
if (noselect) { if (noselect) {
broken = 1; broken = 1;
@ -1859,13 +2118,36 @@ domenuselect(Hookdef dummy, Chdata dat)
zbeep(); zbeep();
molbeg = -1; molbeg = -1;
break; break;
} else if (nolist && cmd != Th(z_undo)) { } else if (nolist && cmd != Th(z_undo) &&
(!mode || cmd != Th(z_backwarddeletechar))) {
ungetkeycmd(); ungetkeycmd();
break; break;
} else if (cmd == Th(z_acceptline)) { } else if (cmd == Th(z_acceptline)) {
if (mode == MM_FSEARCH || mode == MM_BSEARCH) {
mode = 0;
continue;
}
acc = 1; acc = 1;
break; break;
} else if (cmd == Th(z_acceptandinfernexthistory)) { } else if (cmd == Th(z_viinsert)) {
if (mode == MM_INTER)
mode = 0;
else {
int l = strlen(origline);
mode = MM_INTER;
cs = 0;
foredel(ll);
spaceinline(l);
strncpy((char *) line, origline, l);
cs = origcs;
setmstatus(status, NULL, NULL, NULL);
continue;
}
} else if (cmd == Th(z_acceptandinfernexthistory) ||
(mode == MM_INTER && (cmd == Th(z_selfinsert) ||
cmd == Th(z_selfinsertunmeta)))) {
Menustack s = (Menustack) zhalloc(sizeof(*s)); Menustack s = (Menustack) zhalloc(sizeof(*s));
s->prev = u; s->prev = u;
@ -1888,6 +2170,8 @@ domenuselect(Hookdef dummy, Chdata dat)
s->origline = origline; s->origline = origline;
s->origcs = origcs; s->origcs = origcs;
s->origll = origll; s->origll = origll;
s->status = dupstring(status);
s->mode = mode;
menucmp = menuacc = hasoldlist = 0; menucmp = menuacc = hasoldlist = 0;
minfo.cur = NULL; minfo.cur = NULL;
fixsuffix(); fixsuffix();
@ -1897,6 +2181,23 @@ domenuselect(Hookdef dummy, Chdata dat)
invalidate_list(); invalidate_list();
iforcemenu = 1; iforcemenu = 1;
comprecursive = 1; comprecursive = 1;
if (cmd != Th(z_acceptandinfernexthistory)) {
int l = strlen(origline);
cs = 0;
foredel(ll);
spaceinline(l);
strncpy((char *) line, origline, l);
cs = origcs;
if (cmd == Th(z_selfinsert))
selfinsert(zlenoargs);
else
selfinsertunmeta(zlenoargs);
iforcemenu = -1;
} else
mode = 0;
menucomplete(zlenoargs); menucomplete(zlenoargs);
iforcemenu = 0; iforcemenu = 0;
@ -1920,6 +2221,9 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
goto getk; goto getk;
} }
if (cmd != Th(z_acceptandinfernexthistory))
modeline = setmstatus(status, &modecs, &modell, &modelen);
clearlist = listshown = 1; clearlist = listshown = 1;
mselect = (*(minfo.cur))->gnum; mselect = (*(minfo.cur))->gnum;
setwish = wasnext = 1; setwish = wasnext = 1;
@ -1931,6 +2235,7 @@ domenuselect(Hookdef dummy, Chdata dat)
Menustack s = (Menustack) zhalloc(sizeof(*s)); Menustack s = (Menustack) zhalloc(sizeof(*s));
int ol; int ol;
mode = 0;
s->prev = u; s->prev = u;
u = s; u = s;
s->line = dupstring((char *) line); s->line = dupstring((char *) line);
@ -1949,6 +2254,8 @@ domenuselect(Hookdef dummy, Chdata dat)
s->origline = origline; s->origline = origline;
s->origcs = origcs; s->origcs = origcs;
s->origll = origll; s->origll = origll;
s->status = dupstring(status);
s->mode = mode;
accept_last(); accept_last();
handleundo(); handleundo();
comprecursive = 1; comprecursive = 1;
@ -1977,7 +2284,8 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
setwish = 1; setwish = 1;
continue; continue;
} else if (cmd == Th(z_undo)) { } else if (cmd == Th(z_undo) ||
(mode == MM_INTER && cmd == Th(z_backwarddeletechar))) {
int l; int l;
if (!u) if (!u)
@ -2013,12 +2321,17 @@ domenuselect(Hookdef dummy, Chdata dat)
origline = u->origline; origline = u->origline;
origcs = u->origcs; origcs = u->origcs;
origll = u->origll; origll = u->origll;
strcpy(status, u->status);
mode = u->mode;
u = u->prev; u = u->prev;
clearlist = 1; clearlist = 1;
setwish = 1; setwish = 1;
listdat.valid = 0; listdat.valid = 0;
molbeg = -42; molbeg = -42;
if (mode)
continue;
} else if (cmd == Th(z_redisplay)) { } else if (cmd == Th(z_redisplay)) {
redisplay(zlenoargs); redisplay(zlenoargs);
molbeg = -42; molbeg = -42;
@ -2034,6 +2347,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int omline; int omline;
Cmatch **op; Cmatch **op;
mode = 0;
wrap = 0; wrap = 0;
down: down:
@ -2057,7 +2371,7 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
} while (!*p || *p == mtexpl); } while (!*p || mmarked(*p));
if (wrap == 1) if (wrap == 1)
goto right; goto right;
@ -2068,6 +2382,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int omline; int omline;
Cmatch **op; Cmatch **op;
mode = 0;
wrap = 0; wrap = 0;
up: up:
@ -2091,7 +2406,7 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
} while (!*p || *p == mtexpl); } while (!*p || mmarked(*p));
if (wrap == 1) { if (wrap == 1) {
if (mcol == wishcol) if (mcol == wishcol)
@ -2106,6 +2421,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int i = lines - pl - 1, oi = i, ll = 0; int i = lines - pl - 1, oi = i, ll = 0;
Cmatch **lp = NULL; Cmatch **lp = NULL;
mode = 0;
if (mline == mlines - 1) if (mline == mlines - 1)
goto top; goto top;
while (i > 0) { while (i > 0) {
@ -2119,7 +2435,7 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
if (*p && *p != mtexpl) { if (*p && !mmarked(*p)) {
i--; i--;
lp = p; lp = p;
ll = mline; ll = mline;
@ -2133,6 +2449,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int i = lines - pl - 1, oi = i, ll = 0; int i = lines - pl - 1, oi = i, ll = 0;
Cmatch **lp = NULL; Cmatch **lp = NULL;
mode = 0;
if (!mline) if (!mline)
goto bottom; goto bottom;
while (i > 0) { while (i > 0) {
@ -2146,7 +2463,7 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
if (*p || *p != mtexpl) { if (*p || !mmarked(*p)) {
i--; i--;
lp = p; lp = p;
ll = mline; ll = mline;
@ -2158,6 +2475,8 @@ domenuselect(Hookdef dummy, Chdata dat)
int ll; int ll;
Cmatch **lp; Cmatch **lp;
mode = 0;
top: top:
ll = mline; ll = mline;
@ -2167,7 +2486,7 @@ domenuselect(Hookdef dummy, Chdata dat)
p -= mcols; p -= mcols;
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
if (*p && *p != mtexpl) { if (*p && !mmarked(*p)) {
lp = p; lp = p;
ll = mline; ll = mline;
} }
@ -2178,6 +2497,8 @@ domenuselect(Hookdef dummy, Chdata dat)
int ll; int ll;
Cmatch **lp; Cmatch **lp;
mode = 0;
bottom: bottom:
ll = mline; ll = mline;
@ -2187,7 +2508,7 @@ domenuselect(Hookdef dummy, Chdata dat)
p += mcols; p += mcols;
if (adjust_mcol(wishcol, &p, NULL)) if (adjust_mcol(wishcol, &p, NULL))
continue; continue;
if (*p && *p != mtexpl) { if (*p && !mmarked(*p)) {
lp = p; lp = p;
ll = mline; ll = mline;
} }
@ -2198,6 +2519,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int omcol; int omcol;
Cmatch **op; Cmatch **op;
mode = 0;
wrap = 0; wrap = 0;
right: right:
@ -2219,7 +2541,7 @@ domenuselect(Hookdef dummy, Chdata dat)
mcol++; mcol++;
p++; p++;
} }
} while (!*p || *p == mtexpl || (mcol != omcol && *p == *op)); } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
wishcol = mcol; wishcol = mcol;
if (wrap == 2) if (wrap == 2)
@ -2228,6 +2550,7 @@ domenuselect(Hookdef dummy, Chdata dat)
int omcol; int omcol;
Cmatch **op; Cmatch **op;
mode = 0;
wrap = 0; wrap = 0;
left: left:
@ -2249,7 +2572,7 @@ domenuselect(Hookdef dummy, Chdata dat)
mcol--; mcol--;
p--; p--;
} }
} while (!*p || *p == mtexpl || (mcol != omcol && *p == *op)); } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
wishcol = mcol; wishcol = mcol;
if (wrap == 2) { if (wrap == 2) {
@ -2262,9 +2585,10 @@ domenuselect(Hookdef dummy, Chdata dat)
cmd == Th(z_beginningofline) || cmd == Th(z_beginningofline) ||
cmd == Th(z_beginningoflinehist) || cmd == Th(z_beginningoflinehist) ||
cmd == Th(z_vibeginningofline)) { cmd == Th(z_vibeginningofline)) {
mode = 0;
p -= mcol; p -= mcol;
mcol = 0; mcol = 0;
while (!*p || *p == mtexpl) { while (!*p || mmarked(*p)) {
mcol++; mcol++;
p++; p++;
} }
@ -2273,9 +2597,10 @@ domenuselect(Hookdef dummy, Chdata dat)
cmd == Th(z_endofline) || cmd == Th(z_endofline) ||
cmd == Th(z_endoflinehist) || cmd == Th(z_endoflinehist) ||
cmd == Th(z_viendofline)) { cmd == Th(z_viendofline)) {
mode = 0;
p += mcols - mcol - 1; p += mcols - mcol - 1;
mcol = mcols - 1; mcol = mcols - 1;
while (!*p || *p == mtexpl) { while (!*p || mmarked(*p)) {
mcol--; mcol--;
p--; p--;
} }
@ -2285,6 +2610,7 @@ domenuselect(Hookdef dummy, Chdata dat)
Cmgroup g = *pg; Cmgroup g = *pg;
int ol = mline; int ol = mline;
mode = 0;
do { do {
if (mline == mlines - 1) { if (mline == mlines - 1) {
p -= mline * mcols; p -= mline * mcols;
@ -2297,11 +2623,12 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, &pg)) if (adjust_mcol(wishcol, &p, &pg))
continue; continue;
} while (ol != mline && (*pg == g || !*pg || *pg == mgexpl)); } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
} else if (cmd == Th(z_vibackwardblankword)) { } else if (cmd == Th(z_vibackwardblankword)) {
Cmgroup g = *pg; Cmgroup g = *pg;
int ol = mline; int ol = mline;
mode = 0;
do { do {
if (!mline) { if (!mline) {
mline = mlines - 1; mline = mlines - 1;
@ -2314,7 +2641,7 @@ domenuselect(Hookdef dummy, Chdata dat)
} }
if (adjust_mcol(wishcol, &p, &pg)) if (adjust_mcol(wishcol, &p, &pg))
continue; continue;
} while (ol != mline && (*pg == g || !*pg || *pg == mgexpl)); } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
} else if (cmd == Th(z_completeword) || } else if (cmd == Th(z_completeword) ||
cmd == Th(z_expandorcomplete) || cmd == Th(z_expandorcomplete) ||
cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_expandorcompleteprefix) ||
@ -2326,21 +2653,99 @@ domenuselect(Hookdef dummy, Chdata dat)
!strcmp(cmd->nam, "expand-or-complete-prefix") || !strcmp(cmd->nam, "expand-or-complete-prefix") ||
!strcmp(cmd->nam, "menu-complete") || !strcmp(cmd->nam, "menu-complete") ||
!strcmp(cmd->nam, "menu-expand-or-complete")) { !strcmp(cmd->nam, "menu-expand-or-complete")) {
comprecursive = 1; if (mode == MM_INTER) {
do_menucmp(0); origline = modeline;
mselect = (*(minfo.cur))->gnum; origcs = modecs;
setwish = 1; origll = modell;
mline = -1; cs = 0;
foredel(ll);
spaceinline(origll);
strncpy((char *) line, origline, origll);
cs = origcs;
minfo.len = modelen;
} else {
mode = 0;
comprecursive = 1;
do_menucmp(0);
mselect = (*(minfo.cur))->gnum;
setwish = 1;
mline = -1;
}
continue; continue;
} else if (cmd == Th(z_reversemenucomplete) || } else if (cmd == Th(z_reversemenucomplete) ||
!strcmp(cmd->nam, "reverse-menu-complete")) { !strcmp(cmd->nam, "reverse-menu-complete")) {
mode = 0;
comprecursive = 1; comprecursive = 1;
reversemenucomplete(zlenoargs); reversemenucomplete(zlenoargs);
mselect = (*(minfo.cur))->gnum; mselect = (*(minfo.cur))->gnum;
setwish = 1; setwish = 1;
mline = -1; mline = -1;
continue; continue;
} else if (cmd == Th(z_historyincrementalsearchforward) ||
cmd == Th(z_historyincrementalsearchbackward) ||
((mode == MM_FSEARCH || mode == MM_BSEARCH) &&
(cmd == Th(z_selfinsert) ||
cmd == Th(z_selfinsertunmeta)))) {
Cmatch **np, **op = p;
int was = (mode == MM_FSEARCH || mode == MM_BSEARCH);
int ins = (cmd == Th(z_selfinsert) || cmd == Th(z_selfinsertunmeta));
int back = (cmd == Th(z_historyincrementalsearchbackward));
int wrap;
do {
if (was) {
p += wishcol - mcol;
mcol = wishcol;
}
if (!ins) {
if (was) {
if (!*msearchstr && lastsearch) {
msearchstr = dupstring(lastsearch);
mode = 0;
}
} else {
msearchstr = "";
msearchstack = NULL;
}
}
if (cmd == Th(z_selfinsertunmeta)) {
c &= 0x7f;
if (c == '\r')
c = '\n';
}
wrap = 0;
np = msearch(p, ins, (ins ? (mode == MM_BSEARCH) : back),
(was && !ins), &wrap);
if (!ins)
mode = (back ? MM_BSEARCH : MM_FSEARCH);
if (*msearchstr) {
zsfree(lastsearch);
lastsearch = ztrdup(msearchstr);
}
if (np) {
wishcol = mcol;
p = np;
}
adjust_mcol(wishcol, &p, NULL);
} while ((back || cmd == Th(z_historyincrementalsearchforward)) &&
np && !wrap && was && **p == **op);
} else if ((mode == MM_FSEARCH || mode == MM_BSEARCH) &&
cmd == Th(z_backwarddeletechar)) {
int back;
Cmatch **np = msearchpop(&back);
mode = (back ? MM_BSEARCH : MM_FSEARCH);
wishcol = mcol;
if (np) {
p = np;
adjust_mcol(wishcol, &p, NULL);
}
} else if (cmd == Th(z_undefinedkey)) { } else if (cmd == Th(z_undefinedkey)) {
mode = 0;
continue; continue;
} else { } else {
ungetkeycmd(); ungetkeycmd();

View file

@ -744,8 +744,9 @@ do_ambiguous(void)
* unambiguous prefix. */ * unambiguous prefix. */
lastambig = 1; lastambig = 1;
if (usemenu || (haspattern && comppatinsert && if (iforcemenu != -1 &&
!strcmp(comppatinsert, "menu"))) { (usemenu || (haspattern && comppatinsert &&
!strcmp(comppatinsert, "menu")))) {
/* We are in a position to start using menu completion due to one * /* We are in a position to start using menu completion due to one *
* of the menu completion options, or due to the menu-complete- * * of the menu completion options, or due to the menu-complete- *
* word command, or due to using GLOB_COMPLETE which does menu- * * word command, or due to using GLOB_COMPLETE which does menu- *
@ -961,9 +962,10 @@ do_single(Cmatch m)
cs = minfo.pos; cs = minfo.pos;
foredel(l); foredel(l);
if (m->flags & CMF_ALL) if (m->flags & CMF_ALL) {
do_allmatches(0); do_allmatches(0);
else { return;
}
/* And then we insert the new string. */ /* And then we insert the new string. */
minfo.len = instmatch(m, &scs); minfo.len = instmatch(m, &scs);
@ -1136,7 +1138,6 @@ do_single(Cmatch m)
runhookdef(INSERTMATCHHOOK, (void *) &dat); runhookdef(INSERTMATCHHOOK, (void *) &dat);
minfo.cur = om; minfo.cur = om;
} }
}
} }
/* Do completion, given that we are in the middle of a menu completion. We * /* Do completion, given that we are in the middle of a menu completion. We *
@ -1283,6 +1284,9 @@ do_ambig_menu(void)
{ {
Cmatch *mc; Cmatch *mc;
if (iforcemenu == -1)
do_ambiguous();
if (usemenu != 3) { if (usemenu != 3) {
menucmp = 1; menucmp = 1;
menuacc = 0; menuacc = 0;
@ -1324,7 +1328,8 @@ do_ambig_menu(void)
} }
#endif #endif
mc = (minfo.group)->matches + insmnum; mc = (minfo.group)->matches + insmnum;
do_single(*mc); if (iforcemenu != -1)
do_single(*mc);
minfo.cur = mc; minfo.cur = mc;
} }