zsh-workers
 help / color / mirror / code / Atom feed
* Menu selection
@ 2002-06-18  7:57 Sven Wischnowsky
  2002-06-18  9:51 ` Oliver Kiddle
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-06-18  7:57 UTC (permalink / raw)
  To: zsh-workers


Hi

Here is the next version, now including real incremental search
(started by history-incremental-search-{for,back}ward). And patches
for the docs.

Should I commit it?


Bye
  Sven

diff -ur -r ../oz/Completion/Base/Core/_main_complete ./Completion/Base/Core/_main_complete
--- ../oz/Completion/Base/Core/_main_complete	Sun Jun  9 16:03:38 2002
+++ ./Completion/Base/Core/_main_complete	Mon Jun 17 23:37:03 2002
@@ -267,6 +267,19 @@
         unset MENUSELECT
       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
 elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then
   compstate[insert]=''
diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/compsys.yo	Mon Jun 17 23:54:42 2002
@@ -1824,6 +1824,13 @@
 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
 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)
 item(tt(muttrc))(
diff -ur -r ../oz/Doc/Zsh/mod_complist.yo ./Doc/Zsh/mod_complist.yo
--- ../oz/Doc/Zsh/mod_complist.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/mod_complist.yo	Mon Jun 17 23:52:21 2002
@@ -332,6 +332,22 @@
 item(tt(reverse-menu-complete))(
 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 in
+the same way as normally but without leaving menu selection; instead,
+the set of matches will be reduced to contain only those matches the
+changed command line by calling completion again; the completion
+widgets make the longest unabiguous 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()
 
 All movement functions wrap around at the edges; any other zle function not
diff -ur -r ../oz/Src/Zle/compcore.c ./Src/Zle/compcore.c
--- ../oz/Src/Zle/compcore.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compcore.c	Sun Jun  9 16:03:48 2002
@@ -360,7 +360,7 @@
 	haspattern = 1;
     if (iforcemenu) {
 	if (nmatches)
-	    do_ambig_menu();
+            do_ambig_menu();
 	ret = !nmatches;
     } else if (useline < 0)
 	ret = selfinsert(zlenoargs);
diff -ur -r ../oz/Src/Zle/complist.c ./Src/Zle/complist.c
--- ../oz/Src/Zle/complist.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/complist.c	Mon Jun 17 23:44:32 2002
@@ -400,8 +400,12 @@
 
 /* Used in mtab/mgtab, for explanations. */
 
-#define mtexpl ((Cmatch *) 1)
-#define mgexpl ((Cmgroup) 1)
+#define MMARK       ((unsigned long) 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. */
 
@@ -1065,8 +1069,8 @@
 			int mm = (mcols * ml), i;
 
 			for (i = mcols; i--; ) {
-			    mtab[mm + i] = mtexpl;
-			    mgtab[mm + i] = mgexpl;
+			    mtab[mm + i] = mtmark(NULL);
+			    mgtab[mm + i] = mgmark(NULL);
 			}
 		    }
 		    if (stop)
@@ -1381,13 +1385,20 @@
 
     mlastm = m->gnum;
     if (m->disp && (m->flags & CMF_DISPLINE)) {
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = (mcols * ml), i;
 
-	    for (i = mcols; i--; ) {
-		mtab[mm + i] = mp;
-		mgtab[mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = mcols; i--; ) {
+                    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)) {
 	    mlprinted = printfmt(m->disp, 0, 0, 0) / columns;
@@ -1428,13 +1439,20 @@
 	} else
 	    mx = mc * g->width;
 
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = mcols * ml, i;
 
-	    for (i = (width ? width : mcols); i--; ) {
-		mtab[mx + mm + i] = mp;
-		mgtab[mx + mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = (width ? width : mcols); i--; ) {
+                    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)) {
 	    mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
@@ -1675,8 +1693,8 @@
 
     tab -= mcol;
 
-    for (p = wish; p >= 0 && (!tab[p] || tab[p] == mtexpl); p--);
-    for (n = wish; n < mcols && (!tab[n] || tab[n] == mtexpl); n++);
+    for (p = wish; p >= 0 && (!tab[p] || mmarked(tab[p])); p--);
+    for (n = wish; n < mcols && (!tab[n] || mmarked(tab[n])); n++);
     if (n == mcols)
 	n = -1;
 
@@ -1711,21 +1729,221 @@
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
     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)
+{
+    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;
+        }
+    }
+    return NULL;
+}
+
+#define MM_INTER   1
+#define MM_FSEARCH 2
+#define MM_BSEARCH 3
+
 static int
 domenuselect(Hookdef dummy, Chdata dat)
 {
     static Chdata fdat = NULL;
+    static char *lastsearch = NULL;
     Cmatch **p;
     Cmgroup *pg;
     Thingy cmd;
     Menustack u = NULL;
     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 nolist = 0;
+    int nolist = 0, mode = 0, modecs, modell, modelen;
     char *s;
+    char status[MAX_STATUS], *modeline;
+
+    msearchstack = NULL;
+    msearchstr = "";
+    msearchstate = MS_OK;
 
+    status[0] = '\0';
     queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
@@ -1744,6 +1962,21 @@
 	    if ((step += lines - nlnct) < 0)
 		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)
 	mstatus = "%SScrolling active: current selection at %p%s";
     unqueue_signals();
@@ -1770,7 +2003,7 @@
 
 	    for (y = 0; y < mlines; y++) {
 		for (x = mcols; x; x--, p++)
-		    if (*p && *p != mtexpl && **p && mselect == (**p)->gnum)
+		    if (*p && !mmarked(*p) && **p && mselect == (**p)->gnum)
 			break;
 		if (x) {
                     mcol = mcols - x;
@@ -1790,7 +2023,7 @@
 
 	    while (mlbeg) {
 		for (q = p, c = columns; c; q++, c--)
-		    if (*q && *q != mtexpl)
+		    if (*q && !mmarked(*q))
 			break;
 		if (c)
 		    break;
@@ -1821,8 +2054,33 @@
         showinglist = -2;
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
+        if (first) {
+            modeline = dyncat(compprefix, compsuffix);
+            modecs = cs;
+            modell = ll;
+            modelen = minfo.len;
+        }
         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();
+        statusline = NULL;
+        statusll = 0;
         inselect = 1;
         if (noselect) {
             broken = 1;
@@ -1859,13 +2117,36 @@
 	    zbeep();
             molbeg = -1;
 	    break;
-	} else if (nolist && cmd != Th(z_undo)) {
+	} else if (nolist && cmd != Th(z_undo) &&
+                   (!mode || cmd != Th(z_backwarddeletechar))) {
 	    ungetkeycmd();
 	    break;
 	} else if (cmd == Th(z_acceptline)) {
+            if (mode == MM_FSEARCH || mode == MM_BSEARCH) {
+                mode = 0;
+                continue;
+            }
 	    acc = 1;
 	    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));
 
 	    s->prev = u;
@@ -1888,6 +2169,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
 	    fixsuffix();
@@ -1897,6 +2180,23 @@
 	    invalidate_list();
 	    iforcemenu = 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);
 	    iforcemenu = 0;
 
@@ -1920,6 +2220,9 @@
 		}
 		goto getk;
 	    }
+            if (cmd != Th(z_acceptandinfernexthistory))
+                modeline = setmstatus(status, &modecs, &modell, &modelen);
+
 	    clearlist = listshown = 1;
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = wasnext = 1;
@@ -1931,6 +2234,7 @@
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
+            mode = 0;
 	    s->prev = u;
 	    u = s;
 	    s->line = dupstring((char *) line);
@@ -1949,6 +2253,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    accept_last();
 	    handleundo();
 	    comprecursive = 1;
@@ -1977,7 +2283,8 @@
 	    }
 	    setwish = 1;
 	    continue;
-	} else if (cmd == Th(z_undo)) {
+	} else if (cmd == Th(z_undo) ||
+                   (mode == MM_INTER && cmd == Th(z_backwarddeletechar))) {
 	    int l;
 
 	    if (!u)
@@ -2013,12 +2320,17 @@
 	    origline = u->origline;
 	    origcs = u->origcs;
 	    origll = u->origll;
+            strcpy(status, u->status);
+            mode = u->mode;
 
 	    u = u->prev;
 	    clearlist = 1;
 	    setwish = 1;
 	    listdat.valid = 0;
             molbeg = -42;
+
+            if (mode)
+                continue;
 	} else if (cmd == Th(z_redisplay)) {
 	    redisplay(zlenoargs);
             molbeg = -42;
@@ -2034,6 +2346,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	down:
@@ -2057,7 +2370,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1)
 		goto right;
@@ -2068,6 +2381,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	up:
@@ -2091,7 +2405,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1) {
 		if (mcol == wishcol)
@@ -2106,6 +2420,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (mline == mlines - 1)
 		goto top;
 	    while (i > 0) {
@@ -2119,7 +2434,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2133,6 +2448,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (!mline)
 		goto bottom;
 	    while (i > 0) {
@@ -2146,7 +2462,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p || *p != mtexpl) {
+		if (*p || !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2158,6 +2474,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	top:
 
 	    ll = mline;
@@ -2167,7 +2485,7 @@
 		p -= mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2178,6 +2496,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	bottom:
 
 	    ll = mline;
@@ -2187,7 +2507,7 @@
 		p += mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2198,6 +2518,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	right:
@@ -2219,7 +2540,7 @@
 		    mcol++;
 		    p++;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2)
@@ -2228,6 +2549,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	left:
@@ -2249,7 +2571,7 @@
 		    mcol--;
 		    p--;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2) {
@@ -2262,9 +2584,10 @@
 		   cmd == Th(z_beginningofline) ||
 		   cmd == Th(z_beginningoflinehist) ||
 		   cmd == Th(z_vibeginningofline)) {
+            mode = 0;
 	    p -= mcol;
 	    mcol = 0;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol++;
 		p++;
 	    }
@@ -2273,9 +2596,10 @@
 		   cmd == Th(z_endofline) ||
 		   cmd == Th(z_endoflinehist) ||
 		   cmd == Th(z_viendofline)) {
+            mode = 0;
 	    p += mcols - mcol - 1;
 	    mcol = mcols - 1;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol--;
 		p--;
 	    }
@@ -2285,6 +2609,7 @@
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (mline == mlines - 1) {
 		    p -= mline * mcols;
@@ -2297,11 +2622,12 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_vibackwardblankword)) {
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (!mline) {
 		    mline = mlines - 1;
@@ -2314,7 +2640,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_completeword) ||
 		   cmd == Th(z_expandorcomplete) ||
 		   cmd == Th(z_expandorcompleteprefix) ||
@@ -2326,21 +2652,91 @@
 		   !strcmp(cmd->nam, "expand-or-complete-prefix") ||
 		   !strcmp(cmd->nam, "menu-complete") ||
 		   !strcmp(cmd->nam, "menu-expand-or-complete")) {
-	    comprecursive = 1;
-	    do_menucmp(0);
-	    mselect = (*(minfo.cur))->gnum;
-	    setwish = 1;
-	    mline = -1;
+            if (mode == MM_INTER) {
+                origline = modeline;
+                origcs = modecs;
+                origll = modell;
+                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;
 	} else if (cmd == Th(z_reversemenucomplete) ||
 		   !strcmp(cmd->nam, "reverse-menu-complete")) {
+            mode = 0;
 	    comprecursive = 1;
 	    reversemenucomplete(zlenoargs);
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = 1;
 	    mline = -1;
 	    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;
+            int was = (mode == MM_FSEARCH || mode == MM_BSEARCH);
+            int ins = (cmd == Th(z_selfinsert) || cmd == Th(z_selfinsertunmeta));
+            int back = (cmd == Th(z_historyincrementalsearchbackward));
+
+            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';
+            }
+            np = msearch(p, ins, (ins ? (mode == MM_BSEARCH) : back), was);
+
+            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);
+            }
+        } 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)) {
+            mode = 0;
 	    continue;
 	} else {
 	    ungetkeycmd();
diff -ur -r ../oz/Src/Zle/compresult.c ./Src/Zle/compresult.c
--- ../oz/Src/Zle/compresult.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compresult.c	Sun Jun  9 16:03:49 2002
@@ -744,8 +744,9 @@
      * unambiguous prefix.                                               */
     lastambig = 1;
 
-    if (usemenu || (haspattern && comppatinsert &&
-		    !strcmp(comppatinsert, "menu"))) {
+    if (iforcemenu != -1 &&
+        (usemenu || (haspattern && comppatinsert &&
+                     !strcmp(comppatinsert, "menu")))) {
 	/* We are in a position to start using menu completion due to one  *
 	 * of the menu completion options, or due to the menu-complete-    *
 	 * word command, or due to using GLOB_COMPLETE which does menu-    *
@@ -961,9 +962,10 @@
     cs = minfo.pos;
     foredel(l);
 
-    if (m->flags & CMF_ALL)
+    if (m->flags & CMF_ALL) {
 	do_allmatches(0);
-    else {
+        return;
+    }
 
     /* And then we insert the new string. */
     minfo.len = instmatch(m, &scs);
@@ -1136,7 +1138,6 @@
 	runhookdef(INSERTMATCHHOOK, (void *) &dat);
 	minfo.cur = om;
     }
-    }
 }
 
 /* Do completion, given that we are in the middle of a menu completion.  We *
@@ -1283,6 +1284,9 @@
 {
     Cmatch *mc;
 
+    if (iforcemenu == -1)
+        do_ambiguous();
+
     if (usemenu != 3) {
 	menucmp = 1;
 	menuacc = 0;
@@ -1324,7 +1328,8 @@
     }
 #endif
     mc = (minfo.group)->matches + insmnum;
-    do_single(*mc);
+    if (iforcemenu != -1)
+        do_single(*mc);
     minfo.cur = mc;
 }
 

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-18  7:57 Menu selection Sven Wischnowsky
@ 2002-06-18  9:51 ` Oliver Kiddle
  2002-06-19  7:49   ` Sven Wischnowsky
  0 siblings, 1 reply; 21+ messages in thread
From: Oliver Kiddle @ 2002-06-18  9:51 UTC (permalink / raw)
  To: Sven Wischnowsky; +Cc: zsh-workers

On 18 Jun, you wrote:
> 
> Here is the next version, now including real incremental search
> (started by history-incremental-search-{for,back}ward). And patches
> for the docs.

Looks good. I get a seg fault though when I try a failing search when
there are descriptions for the completion matches. Not always though.
I can reproduce it with ls -<tab><tab><ctrl-s>xy

It would also be nice if this could be invoked when scrolling a
completion list, i.e. from the listscroll keymap.

Oliver


This e-mail and any attachment is for authorised use by the intended recipient(s) only.  It may contain proprietary material, confidential information and/or be subject to legal privilege.  It should not be copied, disclosed to, retained or used by, any other party.  If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.  Thank you.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-18  9:51 ` Oliver Kiddle
@ 2002-06-19  7:49   ` Sven Wischnowsky
  2002-06-20 15:52     ` Oliver Kiddle
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-06-19  7:49 UTC (permalink / raw)
  To: zsh-workers


Oliver Kiddle wrote:

> On 18 Jun, you wrote:
> > 
> > Here is the next version, now including real incremental search
> > (started by history-incremental-search-{for,back}ward). And patches
> > for the docs.
> 
> Looks good. I get a seg fault though when I try a failing search when
> there are descriptions for the completion matches. Not always though.
> I can reproduce it with ls -<tab><tab><ctrl-s>xy

That was a rather stupid bug, ahem. It happened only when the prefix
string was found in a description. The code made that description be
selected, which wasn't possible.

> It would also be nice if this could be invoked when scrolling a
> completion list, i.e. from the listscroll keymap.

Nothing for this yet, it's a whole lot more complicated, because
listscroll is done while the completion list is being printed (and
while the internal variables which are needed by searching are being
set).

Below is an improved patch, still not committed.


Bye
  Sven

diff -ur -r ../oz/Completion/Base/Core/_main_complete ./Completion/Base/Core/_main_complete
--- ../oz/Completion/Base/Core/_main_complete	Sun Jun  9 16:03:38 2002
+++ ./Completion/Base/Core/_main_complete	Mon Jun 17 23:37:03 2002
@@ -267,6 +267,19 @@
         unset MENUSELECT
       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
 elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then
   compstate[insert]=''
diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/compsys.yo	Mon Jun 17 23:54:42 2002
@@ -1824,6 +1824,13 @@
 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
 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)
 item(tt(muttrc))(
diff -ur -r ../oz/Doc/Zsh/mod_complist.yo ./Doc/Zsh/mod_complist.yo
--- ../oz/Doc/Zsh/mod_complist.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/mod_complist.yo	Mon Jun 17 23:52:21 2002
@@ -332,6 +332,22 @@
 item(tt(reverse-menu-complete))(
 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 in
+the same way as normally but without leaving menu selection; instead,
+the set of matches will be reduced to contain only those matches the
+changed command line by calling completion again; the completion
+widgets make the longest unabiguous 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()
 
 All movement functions wrap around at the edges; any other zle function not
diff -ur -r ../oz/Src/Zle/compcore.c ./Src/Zle/compcore.c
--- ../oz/Src/Zle/compcore.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compcore.c	Sun Jun  9 16:03:48 2002
@@ -360,7 +360,7 @@
 	haspattern = 1;
     if (iforcemenu) {
 	if (nmatches)
-	    do_ambig_menu();
+            do_ambig_menu();
 	ret = !nmatches;
     } else if (useline < 0)
 	ret = selfinsert(zlenoargs);
diff -ur -r ../oz/Src/Zle/complist.c ./Src/Zle/complist.c
--- ../oz/Src/Zle/complist.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/complist.c	Tue Jun 18 19:14:01 2002
@@ -400,8 +400,12 @@
 
 /* Used in mtab/mgtab, for explanations. */
 
-#define mtexpl ((Cmatch *) 1)
-#define mgexpl ((Cmgroup) 1)
+#define MMARK       ((unsigned long) 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. */
 
@@ -1065,8 +1069,8 @@
 			int mm = (mcols * ml), i;
 
 			for (i = mcols; i--; ) {
-			    mtab[mm + i] = mtexpl;
-			    mgtab[mm + i] = mgexpl;
+			    mtab[mm + i] = mtmark(NULL);
+			    mgtab[mm + i] = mgmark(NULL);
 			}
 		    }
 		    if (stop)
@@ -1381,13 +1385,20 @@
 
     mlastm = m->gnum;
     if (m->disp && (m->flags & CMF_DISPLINE)) {
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = (mcols * ml), i;
 
-	    for (i = mcols; i--; ) {
-		mtab[mm + i] = mp;
-		mgtab[mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = mcols; i--; ) {
+                    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)) {
 	    mlprinted = printfmt(m->disp, 0, 0, 0) / columns;
@@ -1428,13 +1439,20 @@
 	} else
 	    mx = mc * g->width;
 
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = mcols * ml, i;
 
-	    for (i = (width ? width : mcols); i--; ) {
-		mtab[mx + mm + i] = mp;
-		mgtab[mx + mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = (width ? width : mcols); i--; ) {
+                    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)) {
 	    mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
@@ -1675,8 +1693,8 @@
 
     tab -= mcol;
 
-    for (p = wish; p >= 0 && (!tab[p] || tab[p] == mtexpl); p--);
-    for (n = wish; n < mcols && (!tab[n] || tab[n] == mtexpl); n++);
+    for (p = wish; p >= 0 && (!tab[p] || mmarked(tab[p])); p--);
+    for (n = wish; n < mcols && (!tab[n] || mmarked(tab[n])); n++);
     if (n == mcols)
 	n = -1;
 
@@ -1711,21 +1729,221 @@
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
     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)
+{
+    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;
+        }
+    }
+    return NULL;
+}
+
+#define MM_INTER   1
+#define MM_FSEARCH 2
+#define MM_BSEARCH 3
+
 static int
 domenuselect(Hookdef dummy, Chdata dat)
 {
     static Chdata fdat = NULL;
+    static char *lastsearch = NULL;
     Cmatch **p;
     Cmgroup *pg;
     Thingy cmd;
     Menustack u = NULL;
     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 nolist = 0;
+    int nolist = 0, mode = 0, modecs, modell, modelen;
     char *s;
+    char status[MAX_STATUS], *modeline;
+
+    msearchstack = NULL;
+    msearchstr = "";
+    msearchstate = MS_OK;
 
+    status[0] = '\0';
     queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
@@ -1744,6 +1962,21 @@
 	    if ((step += lines - nlnct) < 0)
 		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)
 	mstatus = "%SScrolling active: current selection at %p%s";
     unqueue_signals();
@@ -1770,7 +2003,7 @@
 
 	    for (y = 0; y < mlines; y++) {
 		for (x = mcols; x; x--, p++)
-		    if (*p && *p != mtexpl && **p && mselect == (**p)->gnum)
+		    if (*p && !mmarked(*p) && **p && mselect == (**p)->gnum)
 			break;
 		if (x) {
                     mcol = mcols - x;
@@ -1790,7 +2023,7 @@
 
 	    while (mlbeg) {
 		for (q = p, c = columns; c; q++, c--)
-		    if (*q && *q != mtexpl)
+		    if (*q && !mmarked(*q))
 			break;
 		if (c)
 		    break;
@@ -1821,8 +2054,33 @@
         showinglist = -2;
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
+        if (first) {
+            modeline = dyncat(compprefix, compsuffix);
+            modecs = cs;
+            modell = ll;
+            modelen = minfo.len;
+        }
         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();
+        statusline = NULL;
+        statusll = 0;
         inselect = 1;
         if (noselect) {
             broken = 1;
@@ -1859,13 +2117,36 @@
 	    zbeep();
             molbeg = -1;
 	    break;
-	} else if (nolist && cmd != Th(z_undo)) {
+	} else if (nolist && cmd != Th(z_undo) &&
+                   (!mode || cmd != Th(z_backwarddeletechar))) {
 	    ungetkeycmd();
 	    break;
 	} else if (cmd == Th(z_acceptline)) {
+            if (mode == MM_FSEARCH || mode == MM_BSEARCH) {
+                mode = 0;
+                continue;
+            }
 	    acc = 1;
 	    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));
 
 	    s->prev = u;
@@ -1888,6 +2169,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
 	    fixsuffix();
@@ -1897,6 +2180,23 @@
 	    invalidate_list();
 	    iforcemenu = 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);
 	    iforcemenu = 0;
 
@@ -1920,6 +2220,9 @@
 		}
 		goto getk;
 	    }
+            if (cmd != Th(z_acceptandinfernexthistory))
+                modeline = setmstatus(status, &modecs, &modell, &modelen);
+
 	    clearlist = listshown = 1;
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = wasnext = 1;
@@ -1931,6 +2234,7 @@
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
+            mode = 0;
 	    s->prev = u;
 	    u = s;
 	    s->line = dupstring((char *) line);
@@ -1949,6 +2253,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    accept_last();
 	    handleundo();
 	    comprecursive = 1;
@@ -1977,7 +2283,8 @@
 	    }
 	    setwish = 1;
 	    continue;
-	} else if (cmd == Th(z_undo)) {
+	} else if (cmd == Th(z_undo) ||
+                   (mode == MM_INTER && cmd == Th(z_backwarddeletechar))) {
 	    int l;
 
 	    if (!u)
@@ -2013,12 +2320,17 @@
 	    origline = u->origline;
 	    origcs = u->origcs;
 	    origll = u->origll;
+            strcpy(status, u->status);
+            mode = u->mode;
 
 	    u = u->prev;
 	    clearlist = 1;
 	    setwish = 1;
 	    listdat.valid = 0;
             molbeg = -42;
+
+            if (mode)
+                continue;
 	} else if (cmd == Th(z_redisplay)) {
 	    redisplay(zlenoargs);
             molbeg = -42;
@@ -2034,6 +2346,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	down:
@@ -2057,7 +2370,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1)
 		goto right;
@@ -2068,6 +2381,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	up:
@@ -2091,7 +2405,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1) {
 		if (mcol == wishcol)
@@ -2106,6 +2420,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (mline == mlines - 1)
 		goto top;
 	    while (i > 0) {
@@ -2119,7 +2434,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2133,6 +2448,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (!mline)
 		goto bottom;
 	    while (i > 0) {
@@ -2146,7 +2462,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p || *p != mtexpl) {
+		if (*p || !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2158,6 +2474,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	top:
 
 	    ll = mline;
@@ -2167,7 +2485,7 @@
 		p -= mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2178,6 +2496,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	bottom:
 
 	    ll = mline;
@@ -2187,7 +2507,7 @@
 		p += mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2198,6 +2518,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	right:
@@ -2219,7 +2540,7 @@
 		    mcol++;
 		    p++;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2)
@@ -2228,6 +2549,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	left:
@@ -2249,7 +2571,7 @@
 		    mcol--;
 		    p--;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2) {
@@ -2262,9 +2584,10 @@
 		   cmd == Th(z_beginningofline) ||
 		   cmd == Th(z_beginningoflinehist) ||
 		   cmd == Th(z_vibeginningofline)) {
+            mode = 0;
 	    p -= mcol;
 	    mcol = 0;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol++;
 		p++;
 	    }
@@ -2273,9 +2596,10 @@
 		   cmd == Th(z_endofline) ||
 		   cmd == Th(z_endoflinehist) ||
 		   cmd == Th(z_viendofline)) {
+            mode = 0;
 	    p += mcols - mcol - 1;
 	    mcol = mcols - 1;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol--;
 		p--;
 	    }
@@ -2285,6 +2609,7 @@
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (mline == mlines - 1) {
 		    p -= mline * mcols;
@@ -2297,11 +2622,12 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_vibackwardblankword)) {
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (!mline) {
 		    mline = mlines - 1;
@@ -2314,7 +2640,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_completeword) ||
 		   cmd == Th(z_expandorcomplete) ||
 		   cmd == Th(z_expandorcompleteprefix) ||
@@ -2326,21 +2652,91 @@
 		   !strcmp(cmd->nam, "expand-or-complete-prefix") ||
 		   !strcmp(cmd->nam, "menu-complete") ||
 		   !strcmp(cmd->nam, "menu-expand-or-complete")) {
-	    comprecursive = 1;
-	    do_menucmp(0);
-	    mselect = (*(minfo.cur))->gnum;
-	    setwish = 1;
-	    mline = -1;
+            if (mode == MM_INTER) {
+                origline = modeline;
+                origcs = modecs;
+                origll = modell;
+                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;
 	} else if (cmd == Th(z_reversemenucomplete) ||
 		   !strcmp(cmd->nam, "reverse-menu-complete")) {
+            mode = 0;
 	    comprecursive = 1;
 	    reversemenucomplete(zlenoargs);
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = 1;
 	    mline = -1;
 	    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;
+            int was = (mode == MM_FSEARCH || mode == MM_BSEARCH);
+            int ins = (cmd == Th(z_selfinsert) || cmd == Th(z_selfinsertunmeta));
+            int back = (cmd == Th(z_historyincrementalsearchbackward));
+
+            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';
+            }
+            np = msearch(p, ins, (ins ? (mode == MM_BSEARCH) : back), was);
+
+            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);
+        } 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)) {
+            mode = 0;
 	    continue;
 	} else {
 	    ungetkeycmd();
diff -ur -r ../oz/Src/Zle/compresult.c ./Src/Zle/compresult.c
--- ../oz/Src/Zle/compresult.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compresult.c	Sun Jun  9 16:03:49 2002
@@ -744,8 +744,9 @@
      * unambiguous prefix.                                               */
     lastambig = 1;
 
-    if (usemenu || (haspattern && comppatinsert &&
-		    !strcmp(comppatinsert, "menu"))) {
+    if (iforcemenu != -1 &&
+        (usemenu || (haspattern && comppatinsert &&
+                     !strcmp(comppatinsert, "menu")))) {
 	/* We are in a position to start using menu completion due to one  *
 	 * of the menu completion options, or due to the menu-complete-    *
 	 * word command, or due to using GLOB_COMPLETE which does menu-    *
@@ -961,9 +962,10 @@
     cs = minfo.pos;
     foredel(l);
 
-    if (m->flags & CMF_ALL)
+    if (m->flags & CMF_ALL) {
 	do_allmatches(0);
-    else {
+        return;
+    }
 
     /* And then we insert the new string. */
     minfo.len = instmatch(m, &scs);
@@ -1136,7 +1138,6 @@
 	runhookdef(INSERTMATCHHOOK, (void *) &dat);
 	minfo.cur = om;
     }
-    }
 }
 
 /* Do completion, given that we are in the middle of a menu completion.  We *
@@ -1283,6 +1284,9 @@
 {
     Cmatch *mc;
 
+    if (iforcemenu == -1)
+        do_ambiguous();
+
     if (usemenu != 3) {
 	menucmp = 1;
 	menuacc = 0;
@@ -1324,7 +1328,8 @@
     }
 #endif
     mc = (minfo.group)->matches + insmnum;
-    do_single(*mc);
+    if (iforcemenu != -1)
+        do_single(*mc);
     minfo.cur = mc;
 }
 

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-19  7:49   ` Sven Wischnowsky
@ 2002-06-20 15:52     ` Oliver Kiddle
  2002-06-20 15:58       ` Bart Schaefer
  2002-06-21  9:27       ` Sven Wischnowsky
  0 siblings, 2 replies; 21+ messages in thread
From: Oliver Kiddle @ 2002-06-20 15:52 UTC (permalink / raw)
  To: Sven Wischnowsky; +Cc: zsh-workers

On 19 Jun, you wrote:
> 
> Below is an improved patch, still not committed.

This is good but I have a couple of observations:

If I do ls -<tab><tab><ctrl-s>exc, the prompt changes to `failing
isearch'. It is matching the word `except' and the `c' didn't enable it
to move on to another entry so it says it is failing but this doesn't
seem correct because it is still matching the word `except'. It should
only say failing when there really is nothing found.

Keeping with ls, if I do a search for `co' and then repeatedly press
Ctrl-S to cycle between the matching completions, I have to press Ctrl-S
twice to move off the --color option. Perhaps because `co' matches in
both the match and description.

The binding of backspace to undo is not ideal when cycling between
matches because it goes back through the matches before removing
characters off the end of the search string.

> +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 in
> +the same way as normally but without leaving menu selection; instead,
> +the set of matches will be reduced to contain only those matches the
> +changed command line by calling completion again; the completion
> +widgets make the longest unabiguous string be inserted in the command
> +line and tt(undo) and tt(backward-delete-char) go back to the previous
> +set of matches

Before you commit this, the `m' in unambiguous is missing and the
sentence seems to have a word missing (inserting `for' between `matches'
and `the' would be one fix). I also think the `normally' should be
`normal' but I'm not certain on that.

Oliver

This e-mail and any attachment is for authorised use by the intended recipient(s) only.  It may contain proprietary material, confidential information and/or be subject to legal privilege.  It should not be copied, disclosed to, retained or used by, any other party.  If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.  Thank you.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-20 15:52     ` Oliver Kiddle
@ 2002-06-20 15:58       ` Bart Schaefer
  2002-06-20 16:22         ` Oliver Kiddle
  2002-06-21  9:27       ` Sven Wischnowsky
  1 sibling, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2002-06-20 15:58 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-workers

On Thu, 20 Jun 2002, Oliver Kiddle wrote:

> The binding of backspace to undo is not ideal when cycling between
> matches because it goes back through the matches before removing
> characters off the end of the search string.

That is, of course, how emacs isearch mode works -- so you can back up if
you are pounding C-s and pound it right on past where you really meant to
stop.  What is it that you would prefer?


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-20 15:58       ` Bart Schaefer
@ 2002-06-20 16:22         ` Oliver Kiddle
  0 siblings, 0 replies; 21+ messages in thread
From: Oliver Kiddle @ 2002-06-20 16:22 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

On 20 Jun, you wrote:

> > The binding of backspace to undo is not ideal when cycling between
> > matches because it goes back through the matches before removing
> > characters off the end of the search string.
> 
> That is, of course, how emacs isearch mode works -- so you can back up if

I see that it is also what history-incremental-search-backward does
which is perhaps a better reference point than emacs.

> you are pounding C-s and pound it right on past where you really meant to
> stop.  What is it that you would prefer?

I would prefer it to go straight to chopping off the last character of
the search string. Hitting C-r allows you to back up if needed so I'd
use that.

Perhaps we could have a separate widget for to two options.

Oliver

This e-mail and any attachment is for authorised use by the intended recipient(s) only.  It may contain proprietary material, confidential information and/or be subject to legal privilege.  It should not be copied, disclosed to, retained or used by, any other party.  If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.  Thank you.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-20 15:52     ` Oliver Kiddle
  2002-06-20 15:58       ` Bart Schaefer
@ 2002-06-21  9:27       ` Sven Wischnowsky
  2002-06-26 10:18         ` Sven Wischnowsky
  1 sibling, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-06-21  9:27 UTC (permalink / raw)
  To: zsh-workers


Oliver Kiddle wrote:

> ...
> 
> If I do ls -<tab><tab><ctrl-s>exc, the prompt changes to `failing
> isearch'. It is matching the word `except' and the `c' didn't enable it
> to move on to another entry so it says it is failing but this doesn't
> seem correct because it is still matching the word `except'. It should
> only say failing when there really is nothing found.
> 
> Keeping with ls, if I do a search for `co' and then repeatedly press
> Ctrl-S to cycle between the matching completions, I have to press Ctrl-S
> twice to move off the --color option. Perhaps because `co' matches in
> both the match and description.

These two (and the manual) should be fixed in the new version below.

> The binding of backspace to undo is not ideal when cycling between
> matches because it goes back through the matches before removing
> characters off the end of the search string.

Personally, I prefer it this way, but we can make it optional, of
course, using another widget, as you suggested. I'll have a look.

And next time, I'm going to commit it.


Bye
  Sven

diff -ur -r ../oz/Completion/Base/Core/_main_complete ./Completion/Base/Core/_main_complete
--- ../oz/Completion/Base/Core/_main_complete	Sun Jun  9 16:03:38 2002
+++ ./Completion/Base/Core/_main_complete	Mon Jun 17 23:37:03 2002
@@ -267,6 +267,19 @@
         unset MENUSELECT
       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
 elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then
   compstate[insert]=''
diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/compsys.yo	Mon Jun 17 23:54:42 2002
@@ -1824,6 +1824,13 @@
 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
 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)
 item(tt(muttrc))(
diff -ur -r ../oz/Doc/Zsh/mod_complist.yo ./Doc/Zsh/mod_complist.yo
--- ../oz/Doc/Zsh/mod_complist.yo	Sun Jun  9 16:03:36 2002
+++ ./Doc/Zsh/mod_complist.yo	Thu Jun 20 22:40:20 2002
@@ -332,6 +332,22 @@
 item(tt(reverse-menu-complete))(
 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 in
+the same way as in normal editing mode but without leaving menu
+selection; instead, the set of matches will be reduced to contain only
+those matches the changed command line by calling completion again;
+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()
 
 All movement functions wrap around at the edges; any other zle function not
diff -ur -r ../oz/Src/Zle/compcore.c ./Src/Zle/compcore.c
--- ../oz/Src/Zle/compcore.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compcore.c	Sun Jun  9 16:03:48 2002
@@ -360,7 +360,7 @@
 	haspattern = 1;
     if (iforcemenu) {
 	if (nmatches)
-	    do_ambig_menu();
+            do_ambig_menu();
 	ret = !nmatches;
     } else if (useline < 0)
 	ret = selfinsert(zlenoargs);
diff -ur -r ../oz/Src/Zle/complist.c ./Src/Zle/complist.c
--- ../oz/Src/Zle/complist.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/complist.c	Thu Jun 20 22:35:32 2002
@@ -400,8 +400,12 @@
 
 /* Used in mtab/mgtab, for explanations. */
 
-#define mtexpl ((Cmatch *) 1)
-#define mgexpl ((Cmgroup) 1)
+#define MMARK       ((unsigned long) 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. */
 
@@ -1065,8 +1069,8 @@
 			int mm = (mcols * ml), i;
 
 			for (i = mcols; i--; ) {
-			    mtab[mm + i] = mtexpl;
-			    mgtab[mm + i] = mgexpl;
+			    mtab[mm + i] = mtmark(NULL);
+			    mgtab[mm + i] = mgmark(NULL);
 			}
 		    }
 		    if (stop)
@@ -1381,13 +1385,20 @@
 
     mlastm = m->gnum;
     if (m->disp && (m->flags & CMF_DISPLINE)) {
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = (mcols * ml), i;
 
-	    for (i = mcols; i--; ) {
-		mtab[mm + i] = mp;
-		mgtab[mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = mcols; i--; ) {
+                    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)) {
 	    mlprinted = printfmt(m->disp, 0, 0, 0) / columns;
@@ -1428,13 +1439,20 @@
 	} else
 	    mx = mc * g->width;
 
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = mcols * ml, i;
 
-	    for (i = (width ? width : mcols); i--; ) {
-		mtab[mx + mm + i] = mp;
-		mgtab[mx + mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = (width ? width : mcols); i--; ) {
+                    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)) {
 	    mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
@@ -1675,8 +1693,8 @@
 
     tab -= mcol;
 
-    for (p = wish; p >= 0 && (!tab[p] || tab[p] == mtexpl); p--);
-    for (n = wish; n < mcols && (!tab[n] || tab[n] == mtexpl); n++);
+    for (p = wish; p >= 0 && (!tab[p] || mmarked(tab[p])); p--);
+    for (n = wish; n < mcols && (!tab[n] || mmarked(tab[n])); n++);
     if (n == mcols)
 	n = -1;
 
@@ -1711,21 +1729,222 @@
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
     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
 domenuselect(Hookdef dummy, Chdata dat)
 {
     static Chdata fdat = NULL;
+    static char *lastsearch = NULL;
     Cmatch **p;
     Cmgroup *pg;
     Thingy cmd;
     Menustack u = NULL;
     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 nolist = 0;
+    int nolist = 0, mode = 0, modecs, modell, modelen;
     char *s;
+    char status[MAX_STATUS], *modeline;
 
+    msearchstack = NULL;
+    msearchstr = "";
+    msearchstate = MS_OK;
+
+    status[0] = '\0';
     queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
@@ -1744,6 +1963,21 @@
 	    if ((step += lines - nlnct) < 0)
 		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)
 	mstatus = "%SScrolling active: current selection at %p%s";
     unqueue_signals();
@@ -1770,7 +2004,7 @@
 
 	    for (y = 0; y < mlines; y++) {
 		for (x = mcols; x; x--, p++)
-		    if (*p && *p != mtexpl && **p && mselect == (**p)->gnum)
+		    if (*p && !mmarked(*p) && **p && mselect == (**p)->gnum)
 			break;
 		if (x) {
                     mcol = mcols - x;
@@ -1790,7 +2024,7 @@
 
 	    while (mlbeg) {
 		for (q = p, c = columns; c; q++, c--)
-		    if (*q && *q != mtexpl)
+		    if (*q && !mmarked(*q))
 			break;
 		if (c)
 		    break;
@@ -1821,8 +2055,33 @@
         showinglist = -2;
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
+        if (first) {
+            modeline = dyncat(compprefix, compsuffix);
+            modecs = cs;
+            modell = ll;
+            modelen = minfo.len;
+        }
         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();
+        statusline = NULL;
+        statusll = 0;
         inselect = 1;
         if (noselect) {
             broken = 1;
@@ -1859,13 +2118,36 @@
 	    zbeep();
             molbeg = -1;
 	    break;
-	} else if (nolist && cmd != Th(z_undo)) {
+	} else if (nolist && cmd != Th(z_undo) &&
+                   (!mode || cmd != Th(z_backwarddeletechar))) {
 	    ungetkeycmd();
 	    break;
 	} else if (cmd == Th(z_acceptline)) {
+            if (mode == MM_FSEARCH || mode == MM_BSEARCH) {
+                mode = 0;
+                continue;
+            }
 	    acc = 1;
 	    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));
 
 	    s->prev = u;
@@ -1888,6 +2170,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
 	    fixsuffix();
@@ -1897,6 +2181,23 @@
 	    invalidate_list();
 	    iforcemenu = 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);
 	    iforcemenu = 0;
 
@@ -1920,6 +2221,9 @@
 		}
 		goto getk;
 	    }
+            if (cmd != Th(z_acceptandinfernexthistory))
+                modeline = setmstatus(status, &modecs, &modell, &modelen);
+
 	    clearlist = listshown = 1;
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = wasnext = 1;
@@ -1931,6 +2235,7 @@
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
+            mode = 0;
 	    s->prev = u;
 	    u = s;
 	    s->line = dupstring((char *) line);
@@ -1949,6 +2254,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    accept_last();
 	    handleundo();
 	    comprecursive = 1;
@@ -1977,7 +2284,8 @@
 	    }
 	    setwish = 1;
 	    continue;
-	} else if (cmd == Th(z_undo)) {
+	} else if (cmd == Th(z_undo) ||
+                   (mode == MM_INTER && cmd == Th(z_backwarddeletechar))) {
 	    int l;
 
 	    if (!u)
@@ -2013,12 +2321,17 @@
 	    origline = u->origline;
 	    origcs = u->origcs;
 	    origll = u->origll;
+            strcpy(status, u->status);
+            mode = u->mode;
 
 	    u = u->prev;
 	    clearlist = 1;
 	    setwish = 1;
 	    listdat.valid = 0;
             molbeg = -42;
+
+            if (mode)
+                continue;
 	} else if (cmd == Th(z_redisplay)) {
 	    redisplay(zlenoargs);
             molbeg = -42;
@@ -2034,6 +2347,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	down:
@@ -2057,7 +2371,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1)
 		goto right;
@@ -2068,6 +2382,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	up:
@@ -2091,7 +2406,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1) {
 		if (mcol == wishcol)
@@ -2106,6 +2421,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (mline == mlines - 1)
 		goto top;
 	    while (i > 0) {
@@ -2119,7 +2435,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2133,6 +2449,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (!mline)
 		goto bottom;
 	    while (i > 0) {
@@ -2146,7 +2463,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p || *p != mtexpl) {
+		if (*p || !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2158,6 +2475,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	top:
 
 	    ll = mline;
@@ -2167,7 +2486,7 @@
 		p -= mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2178,6 +2497,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	bottom:
 
 	    ll = mline;
@@ -2187,7 +2508,7 @@
 		p += mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2198,6 +2519,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	right:
@@ -2219,7 +2541,7 @@
 		    mcol++;
 		    p++;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2)
@@ -2228,6 +2550,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	left:
@@ -2249,7 +2572,7 @@
 		    mcol--;
 		    p--;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2) {
@@ -2262,9 +2585,10 @@
 		   cmd == Th(z_beginningofline) ||
 		   cmd == Th(z_beginningoflinehist) ||
 		   cmd == Th(z_vibeginningofline)) {
+            mode = 0;
 	    p -= mcol;
 	    mcol = 0;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol++;
 		p++;
 	    }
@@ -2273,9 +2597,10 @@
 		   cmd == Th(z_endofline) ||
 		   cmd == Th(z_endoflinehist) ||
 		   cmd == Th(z_viendofline)) {
+            mode = 0;
 	    p += mcols - mcol - 1;
 	    mcol = mcols - 1;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol--;
 		p--;
 	    }
@@ -2285,6 +2610,7 @@
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (mline == mlines - 1) {
 		    p -= mline * mcols;
@@ -2297,11 +2623,12 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_vibackwardblankword)) {
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (!mline) {
 		    mline = mlines - 1;
@@ -2314,7 +2641,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_completeword) ||
 		   cmd == Th(z_expandorcomplete) ||
 		   cmd == Th(z_expandorcompleteprefix) ||
@@ -2326,21 +2653,99 @@
 		   !strcmp(cmd->nam, "expand-or-complete-prefix") ||
 		   !strcmp(cmd->nam, "menu-complete") ||
 		   !strcmp(cmd->nam, "menu-expand-or-complete")) {
-	    comprecursive = 1;
-	    do_menucmp(0);
-	    mselect = (*(minfo.cur))->gnum;
-	    setwish = 1;
-	    mline = -1;
+            if (mode == MM_INTER) {
+                origline = modeline;
+                origcs = modecs;
+                origll = modell;
+                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;
 	} else if (cmd == Th(z_reversemenucomplete) ||
 		   !strcmp(cmd->nam, "reverse-menu-complete")) {
+            mode = 0;
 	    comprecursive = 1;
 	    reversemenucomplete(zlenoargs);
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = 1;
 	    mline = -1;
 	    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)) {
+            mode = 0;
 	    continue;
 	} else {
 	    ungetkeycmd();
diff -ur -r ../oz/Src/Zle/compresult.c ./Src/Zle/compresult.c
--- ../oz/Src/Zle/compresult.c	Sun Jun  9 16:03:37 2002
+++ ./Src/Zle/compresult.c	Sun Jun  9 16:03:49 2002
@@ -744,8 +744,9 @@
      * unambiguous prefix.                                               */
     lastambig = 1;
 
-    if (usemenu || (haspattern && comppatinsert &&
-		    !strcmp(comppatinsert, "menu"))) {
+    if (iforcemenu != -1 &&
+        (usemenu || (haspattern && comppatinsert &&
+                     !strcmp(comppatinsert, "menu")))) {
 	/* We are in a position to start using menu completion due to one  *
 	 * of the menu completion options, or due to the menu-complete-    *
 	 * word command, or due to using GLOB_COMPLETE which does menu-    *
@@ -961,9 +962,10 @@
     cs = minfo.pos;
     foredel(l);
 
-    if (m->flags & CMF_ALL)
+    if (m->flags & CMF_ALL) {
 	do_allmatches(0);
-    else {
+        return;
+    }
 
     /* And then we insert the new string. */
     minfo.len = instmatch(m, &scs);
@@ -1136,7 +1138,6 @@
 	runhookdef(INSERTMATCHHOOK, (void *) &dat);
 	minfo.cur = om;
     }
-    }
 }
 
 /* Do completion, given that we are in the middle of a menu completion.  We *
@@ -1283,6 +1284,9 @@
 {
     Cmatch *mc;
 
+    if (iforcemenu == -1)
+        do_ambiguous();
+
     if (usemenu != 3) {
 	menucmp = 1;
 	menuacc = 0;
@@ -1324,7 +1328,8 @@
     }
 #endif
     mc = (minfo.group)->matches + insmnum;
-    do_single(*mc);
+    if (iforcemenu != -1)
+        do_single(*mc);
     minfo.cur = mc;
 }
 

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-06-21  9:27       ` Sven Wischnowsky
@ 2002-06-26 10:18         ` Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2002-06-26 10:18 UTC (permalink / raw)
  To: zsh-workers


Hi

Here is the version with the improved wording in the docs. I haven't
changed the backspace-behaviour (Oliver told me that maybe it's ok ;-)

About adding searching capabilities to list scrolling (without menu
selection): I think it would be too complicated to implement,
especially searching backwards. One can always `select=long-list' for
that. Maybe we should advertise that some more in the docs? (Any
suggestions about how we could do that?)


Bye
  Sven

P.S.: Oliver, we had, it seems. And not only that if I got that right
      yesterday ;-)

Index: Completion/Base/Core/_main_complete
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Core/_main_complete,v
retrieving revision 1.5
diff -u -r1.5 _main_complete
--- Completion/Base/Core/_main_complete	22 Jan 2002 10:22:48 -0000	1.5
+++ Completion/Base/Core/_main_complete	26 Jun 2002 10:11:50 -0000
@@ -267,6 +267,19 @@
         unset MENUSELECT
       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
 elif [[ nm -lt 1 && -n "$_comp_mesg" ]]; then
   compstate[insert]=''
Index: Completion/Zsh/Command/_zstyle
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Command/_zstyle,v
retrieving revision 1.11
diff -u -r1.11 _zstyle
--- Completion/Zsh/Command/_zstyle	23 May 2002 12:16:43 -0000	1.11
+++ Completion/Zsh/Command/_zstyle	26 Jun 2002 10:11:50 -0000
@@ -206,7 +206,8 @@
       ;;
 
     boolauto) 
-      _wanted values expl boolean compadd true false auto select
+      _wanted values expl boolean \
+          compadd true false auto select search search-backward interactive
       ;;
 
     cmdorcont)
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.157
diff -u -r1.157 compsys.yo
--- Doc/Zsh/compsys.yo	23 May 2002 12:16:43 -0000	1.157
+++ Doc/Zsh/compsys.yo	26 Jun 2002 10:11:50 -0000
@@ -1824,6 +1824,13 @@
 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
 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)
 item(tt(muttrc))(
Index: Doc/Zsh/mod_complist.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_complist.yo,v
retrieving revision 1.15
diff -u -r1.15 mod_complist.yo
--- Doc/Zsh/mod_complist.yo	28 May 2001 16:01:02 -0000	1.15
+++ Doc/Zsh/mod_complist.yo	26 Jun 2002 10:11:51 -0000
@@ -332,6 +332,22 @@
 item(tt(reverse-menu-complete))(
 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()
 
 All movement functions wrap around at the edges; any other zle function not
Index: Src/Zle/compcore.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v
retrieving revision 1.60
diff -u -r1.60 compcore.c
--- Src/Zle/compcore.c	21 May 2002 08:07:51 -0000	1.60
+++ Src/Zle/compcore.c	26 Jun 2002 10:11:51 -0000
@@ -360,7 +360,7 @@
 	haspattern = 1;
     if (iforcemenu) {
 	if (nmatches)
-	    do_ambig_menu();
+            do_ambig_menu();
 	ret = !nmatches;
     } else if (useline < 0)
 	ret = selfinsert(zlenoargs);
Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.50
diff -u -r1.50 complist.c
--- Src/Zle/complist.c	5 Jun 2002 07:49:05 -0000	1.50
+++ Src/Zle/complist.c	26 Jun 2002 10:11:51 -0000
@@ -400,8 +400,12 @@
 
 /* Used in mtab/mgtab, for explanations. */
 
-#define mtexpl ((Cmatch *) 1)
-#define mgexpl ((Cmgroup) 1)
+#define MMARK       ((unsigned long) 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. */
 
@@ -1065,8 +1069,8 @@
 			int mm = (mcols * ml), i;
 
 			for (i = mcols; i--; ) {
-			    mtab[mm + i] = mtexpl;
-			    mgtab[mm + i] = mgexpl;
+			    mtab[mm + i] = mtmark(NULL);
+			    mgtab[mm + i] = mgmark(NULL);
 			}
 		    }
 		    if (stop)
@@ -1381,13 +1385,20 @@
 
     mlastm = m->gnum;
     if (m->disp && (m->flags & CMF_DISPLINE)) {
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = (mcols * ml), i;
 
-	    for (i = mcols; i--; ) {
-		mtab[mm + i] = mp;
-		mgtab[mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = mcols; i--; ) {
+                    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)) {
 	    mlprinted = printfmt(m->disp, 0, 0, 0) / columns;
@@ -1428,13 +1439,20 @@
 	} else
 	    mx = mc * g->width;
 
-	if (mselect >= 0 && !(m->flags & CMF_DUMMY)) {
+	if (mselect >= 0) {
 	    int mm = mcols * ml, i;
 
-	    for (i = (width ? width : mcols); i--; ) {
-		mtab[mx + mm + i] = mp;
-		mgtab[mx + mm + i] = g;
-	    }
+            if (m->flags & CMF_DUMMY) {
+                for (i = (width ? width : mcols); i--; ) {
+                    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)) {
 	    mlprinted = niceztrlen(m->disp ? m->disp : m->str) / columns;
@@ -1675,8 +1693,8 @@
 
     tab -= mcol;
 
-    for (p = wish; p >= 0 && (!tab[p] || tab[p] == mtexpl); p--);
-    for (n = wish; n < mcols && (!tab[n] || tab[n] == mtexpl); n++);
+    for (p = wish; p >= 0 && (!tab[p] || mmarked(tab[p])); p--);
+    for (n = wish; n < mcols && (!tab[n] || mmarked(tab[n])); n++);
     if (n == mcols)
 	n = -1;
 
@@ -1711,21 +1729,222 @@
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
     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
 domenuselect(Hookdef dummy, Chdata dat)
 {
     static Chdata fdat = NULL;
+    static char *lastsearch = NULL;
     Cmatch **p;
     Cmgroup *pg;
     Thingy cmd;
     Menustack u = NULL;
     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 nolist = 0;
+    int nolist = 0, mode = 0, modecs, modell, modelen;
     char *s;
+    char status[MAX_STATUS], *modeline;
 
+    msearchstack = NULL;
+    msearchstr = "";
+    msearchstate = MS_OK;
+
+    status[0] = '\0';
     queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
@@ -1744,6 +1963,21 @@
 	    if ((step += lines - nlnct) < 0)
 		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)
 	mstatus = "%SScrolling active: current selection at %p%s";
     unqueue_signals();
@@ -1770,7 +2004,7 @@
 
 	    for (y = 0; y < mlines; y++) {
 		for (x = mcols; x; x--, p++)
-		    if (*p && *p != mtexpl && **p && mselect == (**p)->gnum)
+		    if (*p && !mmarked(*p) && **p && mselect == (**p)->gnum)
 			break;
 		if (x) {
                     mcol = mcols - x;
@@ -1790,7 +2024,7 @@
 
 	    while (mlbeg) {
 		for (q = p, c = columns; c; q++, c--)
-		    if (*q && *q != mtexpl)
+		    if (*q && !mmarked(*q))
 			break;
 		if (c)
 		    break;
@@ -1821,8 +2055,33 @@
         showinglist = -2;
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
+        if (first) {
+            modeline = dyncat(compprefix, compsuffix);
+            modecs = cs;
+            modell = ll;
+            modelen = minfo.len;
+        }
         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();
+        statusline = NULL;
+        statusll = 0;
         inselect = 1;
         if (noselect) {
             broken = 1;
@@ -1859,13 +2118,36 @@
 	    zbeep();
             molbeg = -1;
 	    break;
-	} else if (nolist && cmd != Th(z_undo)) {
+	} else if (nolist && cmd != Th(z_undo) &&
+                   (!mode || cmd != Th(z_backwarddeletechar))) {
 	    ungetkeycmd();
 	    break;
 	} else if (cmd == Th(z_acceptline)) {
+            if (mode == MM_FSEARCH || mode == MM_BSEARCH) {
+                mode = 0;
+                continue;
+            }
 	    acc = 1;
 	    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));
 
 	    s->prev = u;
@@ -1888,6 +2170,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
 	    fixsuffix();
@@ -1897,6 +2181,23 @@
 	    invalidate_list();
 	    iforcemenu = 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);
 	    iforcemenu = 0;
 
@@ -1920,6 +2221,9 @@
 		}
 		goto getk;
 	    }
+            if (cmd != Th(z_acceptandinfernexthistory))
+                modeline = setmstatus(status, &modecs, &modell, &modelen);
+
 	    clearlist = listshown = 1;
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = wasnext = 1;
@@ -1931,6 +2235,7 @@
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
+            mode = 0;
 	    s->prev = u;
 	    u = s;
 	    s->line = dupstring((char *) line);
@@ -1949,6 +2254,8 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
+            s->mode = mode;
 	    accept_last();
 	    handleundo();
 	    comprecursive = 1;
@@ -1977,7 +2284,8 @@
 	    }
 	    setwish = 1;
 	    continue;
-	} else if (cmd == Th(z_undo)) {
+	} else if (cmd == Th(z_undo) ||
+                   (mode == MM_INTER && cmd == Th(z_backwarddeletechar))) {
 	    int l;
 
 	    if (!u)
@@ -2013,12 +2321,17 @@
 	    origline = u->origline;
 	    origcs = u->origcs;
 	    origll = u->origll;
+            strcpy(status, u->status);
+            mode = u->mode;
 
 	    u = u->prev;
 	    clearlist = 1;
 	    setwish = 1;
 	    listdat.valid = 0;
             molbeg = -42;
+
+            if (mode)
+                continue;
 	} else if (cmd == Th(z_redisplay)) {
 	    redisplay(zlenoargs);
             molbeg = -42;
@@ -2034,6 +2347,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	down:
@@ -2057,7 +2371,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1)
 		goto right;
@@ -2068,6 +2382,7 @@
 	    int omline;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	up:
@@ -2091,7 +2406,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-	    } while (!*p || *p == mtexpl);
+	    } while (!*p || mmarked(*p));
 
 	    if (wrap == 1) {
 		if (mcol == wishcol)
@@ -2106,6 +2421,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (mline == mlines - 1)
 		goto top;
 	    while (i > 0) {
@@ -2119,7 +2435,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2133,6 +2449,7 @@
 	    int i = lines - pl - 1, oi = i, ll = 0;
 	    Cmatch **lp = NULL;
 
+            mode = 0;
 	    if (!mline)
 		goto bottom;
 	    while (i > 0) {
@@ -2146,7 +2463,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p || *p != mtexpl) {
+		if (*p || !mmarked(*p)) {
 		    i--;
 		    lp = p;
 		    ll = mline;
@@ -2158,6 +2475,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	top:
 
 	    ll = mline;
@@ -2167,7 +2486,7 @@
 		p -= mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2178,6 +2497,8 @@
 	    int ll;
 	    Cmatch **lp;
 
+            mode = 0;
+
 	bottom:
 
 	    ll = mline;
@@ -2187,7 +2508,7 @@
 		p += mcols;
 		if (adjust_mcol(wishcol, &p, NULL))
 		    continue;
-		if (*p && *p != mtexpl) {
+		if (*p && !mmarked(*p)) {
 		    lp = p;
 		    ll = mline;
 		}
@@ -2198,6 +2519,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	right:
@@ -2219,7 +2541,7 @@
 		    mcol++;
 		    p++;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2)
@@ -2228,6 +2550,7 @@
 	    int omcol;
 	    Cmatch **op;
 
+            mode = 0;
 	    wrap = 0;
 
 	left:
@@ -2249,7 +2572,7 @@
 		    mcol--;
 		    p--;
 		}
-	    } while (!*p || *p == mtexpl || (mcol != omcol && *p == *op));
+	    } while (!*p || mmarked(*p) || (mcol != omcol && *p == *op));
 	    wishcol = mcol;
 
 	    if (wrap == 2) {
@@ -2262,9 +2585,10 @@
 		   cmd == Th(z_beginningofline) ||
 		   cmd == Th(z_beginningoflinehist) ||
 		   cmd == Th(z_vibeginningofline)) {
+            mode = 0;
 	    p -= mcol;
 	    mcol = 0;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol++;
 		p++;
 	    }
@@ -2273,9 +2597,10 @@
 		   cmd == Th(z_endofline) ||
 		   cmd == Th(z_endoflinehist) ||
 		   cmd == Th(z_viendofline)) {
+            mode = 0;
 	    p += mcols - mcol - 1;
 	    mcol = mcols - 1;
-	    while (!*p || *p == mtexpl) {
+	    while (!*p || mmarked(*p)) {
 		mcol--;
 		p--;
 	    }
@@ -2285,6 +2610,7 @@
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (mline == mlines - 1) {
 		    p -= mline * mcols;
@@ -2297,11 +2623,12 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_vibackwardblankword)) {
 	    Cmgroup g = *pg;
 	    int ol = mline;
 
+            mode = 0;
 	    do {
 		if (!mline) {
 		    mline = mlines - 1;
@@ -2314,7 +2641,7 @@
 		}
 		if (adjust_mcol(wishcol, &p, &pg))
 		    continue;
-	    } while (ol != mline && (*pg == g || !*pg || *pg == mgexpl));
+	    } while (ol != mline && (*pg == g || !*pg || mmarked(*pg)));
 	} else if (cmd == Th(z_completeword) ||
 		   cmd == Th(z_expandorcomplete) ||
 		   cmd == Th(z_expandorcompleteprefix) ||
@@ -2326,21 +2653,99 @@
 		   !strcmp(cmd->nam, "expand-or-complete-prefix") ||
 		   !strcmp(cmd->nam, "menu-complete") ||
 		   !strcmp(cmd->nam, "menu-expand-or-complete")) {
-	    comprecursive = 1;
-	    do_menucmp(0);
-	    mselect = (*(minfo.cur))->gnum;
-	    setwish = 1;
-	    mline = -1;
+            if (mode == MM_INTER) {
+                origline = modeline;
+                origcs = modecs;
+                origll = modell;
+                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;
 	} else if (cmd == Th(z_reversemenucomplete) ||
 		   !strcmp(cmd->nam, "reverse-menu-complete")) {
+            mode = 0;
 	    comprecursive = 1;
 	    reversemenucomplete(zlenoargs);
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = 1;
 	    mline = -1;
 	    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)) {
+            mode = 0;
 	    continue;
 	} else {
 	    ungetkeycmd();
Index: Src/Zle/compresult.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compresult.c,v
retrieving revision 1.44
diff -u -r1.44 compresult.c
--- Src/Zle/compresult.c	21 May 2002 08:07:51 -0000	1.44
+++ Src/Zle/compresult.c	26 Jun 2002 10:11:51 -0000
@@ -744,8 +744,9 @@
      * unambiguous prefix.                                               */
     lastambig = 1;
 
-    if (usemenu || (haspattern && comppatinsert &&
-		    !strcmp(comppatinsert, "menu"))) {
+    if (iforcemenu != -1 &&
+        (usemenu || (haspattern && comppatinsert &&
+                     !strcmp(comppatinsert, "menu")))) {
 	/* We are in a position to start using menu completion due to one  *
 	 * of the menu completion options, or due to the menu-complete-    *
 	 * word command, or due to using GLOB_COMPLETE which does menu-    *
@@ -961,9 +962,10 @@
     cs = minfo.pos;
     foredel(l);
 
-    if (m->flags & CMF_ALL)
+    if (m->flags & CMF_ALL) {
 	do_allmatches(0);
-    else {
+        return;
+    }
 
     /* And then we insert the new string. */
     minfo.len = instmatch(m, &scs);
@@ -1136,7 +1138,6 @@
 	runhookdef(INSERTMATCHHOOK, (void *) &dat);
 	minfo.cur = om;
     }
-    }
 }
 
 /* Do completion, given that we are in the middle of a menu completion.  We *
@@ -1283,6 +1284,9 @@
 {
     Cmatch *mc;
 
+    if (iforcemenu == -1)
+        do_ambiguous();
+
     if (usemenu != 3) {
 	menucmp = 1;
 	menuacc = 0;
@@ -1324,7 +1328,8 @@
     }
 #endif
     mc = (minfo.group)->matches + insmnum;
-    do_single(*mc);
+    if (iforcemenu != -1)
+        do_single(*mc);
     minfo.cur = mc;
 }
 

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-07-24 23:01           ` Felix Rosencrantz
@ 2002-07-30  7:47             ` Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2002-07-30  7:47 UTC (permalink / raw)
  To: zsh-workers


Felix Rosencrantz wrote:

> Sorry to be the bearer of bad news...
> 
> I'm still seeing problems with the changes made to menu-select/vi-insert.
> Below is the same simple recipe that causes the problem.  Also, attached is the
> output of this recipe run under valgrind.   It points to memory reads of
> data that has already been free'd.
> 
> I actually don't really use this functionality much, but hope it might
> someday be used in a version of history-incremental-search-*ward.
> So that the incremental search can use a matching-spec....

Sigh. You're right, invalidatelist() could be called at the wrong time.


Bye
  Sven

Index: Src/Zle/compresult.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compresult.c,v
retrieving revision 1.45
diff -u -r1.45 compresult.c
--- Src/Zle/compresult.c	26 Jun 2002 11:07:46 -0000	1.45
+++ Src/Zle/compresult.c	30 Jul 2002 07:45:30 -0000
@@ -813,7 +813,7 @@
 	 * want to enter an AUTO_MENU imediately.                          */
 	if ((uselist == 3 ||
 	     (!uselist && isset(BASHAUTOLIST) && isset(LISTAMBIGUOUS))) &&
-	    la) {
+	    la && iforcemenu != -1) {
 	    int fc = fromcomp;
 
 	    invalidatelist();

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-07-05  8:09         ` Sven Wischnowsky
@ 2002-07-24 23:01           ` Felix Rosencrantz
  2002-07-30  7:47             ` Sven Wischnowsky
  0 siblings, 1 reply; 21+ messages in thread
From: Felix Rosencrantz @ 2002-07-24 23:01 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

Sorry to be the bearer of bad news...

I'm still seeing problems with the changes made to menu-select/vi-insert.
Below is the same simple recipe that causes the problem.  Also, attached is the
output of this recipe run under valgrind.   It points to memory reads of
data that has already been free'd.

I actually don't really use this functionality much, but hope it might
someday be used in a version of history-incremental-search-*ward.
So that the incremental search can use a matching-spec....

-FR.

host% autoload -U compinit; compinit -D
host% zmodload zsh/complist
host% bindkey "^Bm" menu-select
host% bindkey "^Bi" vi-insert
host% mkdir bug ; cd bug
host% touch a  a-b.c  a-c.d  a.b.c  b  ba  bb  c
host% more ^Bm^Bia.
interactive: a.b.c[]
BUG: listmatches called with bogus list




==12482== valgrind-1.0pre6, a memory error detector for x86 GNU/Linux.
==12482== Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.
==12482== Invalid read of size 4
==12482==    at 0x4126C911: do_ambig_menu (compresult.c:1318)
==12482==    by 0x4125A75A: do_completion (compcore.c:364)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482==    by 0x411E7E83: docompletion (zle_tricky.c:1824)
==12482==    Address 0x43566084 is 16 bytes inside a block of size 112 free'd
==12482==    at 0x40046A09: free (vg_clientfuncs.c:171)
==12482==    by 0x412639B4: freematches (compcore.c:3072)
==12482==    by 0x4126F5D2: invalidate_list (compresult.c:2175)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482== 
==12482== Invalid read of size 4
==12482==    at 0x4126C98D: do_ambig_menu (compresult.c:1330)
==12482==    by 0x4125A75A: do_completion (compcore.c:364)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482==    by 0x411E7E83: docompletion (zle_tricky.c:1824)
==12482==    Address 0x43566088 is 20 bytes inside a block of size 112 free'd
==12482==    at 0x40046A09: free (vg_clientfuncs.c:171)
==12482==    by 0x412639B4: freematches (compcore.c:3072)
==12482==    by 0x4126F5D2: invalidate_list (compresult.c:2175)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482== 
==12482== Invalid read of size 4
==12482==    at 0x439299D4: domenuselect (complist.c:2219)
==12482==    by 0x4392B8A3: menuselect (complist.c:2847)
==12482==    by 0x411D6EBE: execzlefunc (zle_main.c:862)
==12482==    by 0x411D65DA: zlecore (zle_main.c:660)
==12482==    Address 0x43566114 is 0 bytes inside a block of size 8 free'd
==12482==    at 0x40046A09: free (vg_clientfuncs.c:171)
==12482==    by 0x41263926: freematches (compcore.c:3058)
==12482==    by 0x4126F5D2: invalidate_list (compresult.c:2175)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482== 
==12482== Invalid read of size 4
==12482==    at 0x43929B1E: domenuselect (complist.c:2247)
==12482==    by 0x4392B8A3: menuselect (complist.c:2847)
==12482==    by 0x411D6EBE: execzlefunc (zle_main.c:862)
==12482==    by 0x411D65DA: zlecore (zle_main.c:660)
==12482==    Address 0x43566114 is 0 bytes inside a block of size 8 free'd
==12482==    at 0x40046A09: free (vg_clientfuncs.c:171)
==12482==    by 0x41263926: freematches (compcore.c:3058)
==12482==    by 0x4126F5D2: invalidate_list (compresult.c:2175)
==12482==    by 0x8090E23: runhookdef (module.c:1858)
==12482== 
==12482== Invalid read of size 4
==12482==    at 0x43929B23: domenuselect (complist.c:2247)
==12482==    by 0x4392B8A3: menuselect (complist.c:2847)
==12482==    by 0x411D6EBE: execzlefunc (zle_main.c:862)
==12482==    by 0x411D65DA: zlecore (zle_main.c:660)
==12482==    Address 0x4357A618 is 80 bytes inside a block of size 92 free'd
==12482==    at 0x40046A09: free (vg_clientfuncs.c:171)
==12482==    by 0x808CBDB: zfree (mem.c:1391)
==12482==    by 0x412638AC: freematch (compcore.c:3040)
==12482==    by 0x4126390D: freematches (compcore.c:3057)


__________________________________________________
Do You Yahoo!?
Yahoo! Autos - Get free new car price quotes
http://autos.yahoo.com


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-07-04 17:56       ` Felix Rosencrantz
@ 2002-07-05  8:09         ` Sven Wischnowsky
  2002-07-24 23:01           ` Felix Rosencrantz
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-07-05  8:09 UTC (permalink / raw)
  To: zsh-workers


Felix Rosencrantz wrote:

> It's more robust, but still seeing some problems.  He is the use case.
> I was able to get my shell to crash, but not with this use case.  
> The use case does scream BUG, so hopefully that will help track the problem.

Urgh, it gets embarassing.

And I can't reproduce this either. In fact, I had seen something like
this before the last patch and fixed it. At least I thought I did.

That message should mean that somehow `showinglist' gets set to `-2'
when leavin menu selection even though there isn't a list to show. I
can only try to make the tests a bit more secure (by also testing
`nolist').

The other hunks improve the behaviour of interactive mode when the
string typed doesn't match anything (it doesn't leave menu selection
so that one can use undo and backspace to go back).


Bye
  Sven

Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.53
diff -u -r1.53 complist.c
--- Src/Zle/complist.c	4 Jul 2002 09:29:22 -0000	1.53
+++ Src/Zle/complist.c	5 Jul 2002 08:06:45 -0000
@@ -1724,7 +1724,7 @@
     Brinfo brbeg;
     Brinfo brend;
     int nbrbeg, nbrend;
-    int cs, acc, nmatches, mline, mlbeg;
+    int cs, acc, nmatches, mline, mlbeg, nolist;
     struct menuinfo info;
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
@@ -1768,10 +1768,13 @@
         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';
-
+        if (lastend < cs)
+            s = "";
+        else {
+            s = (char *) zhalloc(lastend - cs + 1);
+            strncpy(s, (char *) line + cs, lastend - cs);
+            s[lastend - cs] = '\0';
+        }
         cs = 0;
         foredel(ll);
         spaceinline(sll);
@@ -2117,7 +2120,9 @@
             molbeg = -1;
 	    break;
 	} else if (nolist && cmd != Th(z_undo) &&
-                   (!mode || cmd != Th(z_backwarddeletechar))) {
+                   (!mode || (cmd != Th(z_backwarddeletechar) &&
+                              cmd != Th(z_selfinsert) &&
+                              cmd != Th(z_selfinsertunmeta)))) {
 	    ungetkeycmd();
 	    break;
 	} else if (cmd == Th(z_acceptline)) {
@@ -2162,6 +2167,7 @@
 	    s->pmatches = pmatches;
 	    s->lastmatches = lastmatches;
 	    s->lastlmatches = lastlmatches;
+            s->nolist = nolist;
 	    s->acc = menuacc;
 	    s->brbeg = dupbrinfo(brbeg, NULL, 1);
 	    s->brend = dupbrinfo(brend, NULL, 1);
@@ -2258,6 +2264,7 @@
 	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
 	    s->amatches = s->pmatches =
 		s->lastmatches = s->lastlmatches = NULL;
+            s->nolist = nolist;
 	    s->acc = menuacc;
 	    s->brbeg = dupbrinfo(brbeg, NULL, 1);
 	    s->brend = dupbrinfo(brend, NULL, 1);
@@ -2305,7 +2312,7 @@
 		break;
 
 	    handleundo();
-	    cs = nolist = 0;
+	    cs = 0;
 	    foredel(ll);
 	    spaceinline(l = strlen(u->line));
 	    strncpy((char *) line, u->line, l);
@@ -2336,6 +2343,7 @@
 	    origll = u->origll;
             strcpy(status, u->status);
             mode = u->mode;
+            nolist = u->nolist;
 
 	    u = u->prev;
 	    clearlist = 1;
@@ -2343,6 +2351,16 @@
 	    listdat.valid = 0;
             molbeg = -42;
 
+            if (nolist) {
+                if (mode == MM_INTER) {
+                    statusline = status;
+                    statusll = strlen(status);
+                }
+                zrefresh();
+                statusline = NULL;
+                statusll = 0;
+                goto getk;
+            }
             if (mode)
                 continue;
 	} else if (cmd == Th(z_redisplay)) {
@@ -2781,13 +2799,15 @@
     mselect = mlastcols = mlastlines = -1;
     mstatus = NULL;
     inselect = mhasstat = 0;
+    if (nolist)
+        clearlist = listshown = 1;
     if (acc && validlist && minfo.cur) {
 	menucmp = lastambig = hasoldlist = 0;
 	do_single(*(minfo.cur));
     }
     if (wasnext || broken) {
 	menucmp = 2;
-	showinglist = (validlist ? -2 : 0);
+	showinglist = ((validlist && !nolist) ? -2 : 0);
 	minfo.asked = 0;
 	if (!noselect) {
 	    int nos = noselect;
@@ -2797,10 +2817,10 @@
 	}
     }
     if (!noselect && (!dat || acc)) {
-	showinglist = (validlist ? -2 : 0);
+	showinglist = ((validlist && !nolist) ? -2 : 0);
 	onlyexpl = oe;
 	if (!smatches)
-	    clearlist = 1;
+	    clearlist = listshown = 1;
 	zrefresh();
     }
     mlbeg = -1;

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-07-04  9:27     ` Sven Wischnowsky
@ 2002-07-04 17:56       ` Felix Rosencrantz
  2002-07-05  8:09         ` Sven Wischnowsky
  0 siblings, 1 reply; 21+ messages in thread
From: Felix Rosencrantz @ 2002-07-04 17:56 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

It's more robust, but still seeing some problems.  He is the use case.
I was able to get my shell to crash, but not with this use case.  
The use case does scream BUG, so hopefully that will help track the problem.

-FR

host% autoload -U compinit; compinit -D
host% zmodload zsh/complist
host% bindkey "^Bm" menu-select
host% bindkey "^Bi" vi-insert
host% mkdir bug ; cd bug
host% touch a  a-b.c  a-c.d  a.b.c  b  ba  bb  c
host% more <^Bm><^Bi>a.
interactive: a.b.c[]
BUG: listmatches called with bogus list


--- Sven Wischnowsky <wischnow@berkom.de> wrote:
> 
> Hi
> 
> Felix mailed me again to say that he still got a crash. I couldn't
> reproduce it anymore, but hope the patch below finally fixes it.
> Felix, does it?
> 
> The patch also fixes problems in the command line display when using
> interactive mode, e.g. after ${<TAB>.
> 
> 
> Bye
>   Sven


__________________________________________________
Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free
http://sbc.yahoo.com


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-07-03  7:58   ` Sven Wischnowsky
@ 2002-07-04  9:27     ` Sven Wischnowsky
  2002-07-04 17:56       ` Felix Rosencrantz
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-07-04  9:27 UTC (permalink / raw)
  To: zsh-workers


Hi

Felix mailed me again to say that he still got a crash. I couldn't
reproduce it anymore, but hope the patch below finally fixes it.
Felix, does it?

The patch also fixes problems in the command line display when using
interactive mode, e.g. after ${<TAB>.


Bye
  Sven

Index: Src/Zle/compcore.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v
retrieving revision 1.62
diff -u -r1.62 compcore.c
--- Src/Zle/compcore.c	1 Jul 2002 08:25:17 -0000	1.62
+++ Src/Zle/compcore.c	4 Jul 2002 09:22:27 -0000
@@ -670,6 +670,10 @@
 	    untokenize(ss);
 	    compsuffix = ztrdup(ss);
 	}
+        zsfree(complastprefix);
+        zsfree(complastsuffix);
+        complastprefix = ztrdup(compprefix);
+        complastsuffix = ztrdup(compsuffix);
 	zsfree(compiprefix);
 	zsfree(compisuffix);
 	if (parwb < 0) {
Index: Src/Zle/complete.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complete.c,v
retrieving revision 1.21
diff -u -r1.21 complete.c
--- Src/Zle/complete.c	24 Apr 2002 07:59:19 -0000	1.21
+++ Src/Zle/complete.c	4 Jul 2002 09:22:27 -0000
@@ -46,6 +46,8 @@
      **compredirs,
      *compprefix,
      *compsuffix,
+     *complastprefix,
+     *complastsuffix,
      *compisuffix,
      *compqiprefix,
      *compqisuffix,
@@ -1405,6 +1407,8 @@
 	compexact = compexactstr = comppatmatch = comppatinsert =
 	complastprompt = comptoend = compoldlist = compoldins =
 	compvared = compqstack = NULL;
+    complastprefix = ztrdup("");
+    complastsuffix = ztrdup("");
     complistmax = 0;
     hascompmod = 1;
 
@@ -1458,6 +1462,8 @@
 	freearray(compredirs);
     zsfree(compprefix);
     zsfree(compsuffix);
+    zsfree(complastprefix);
+    zsfree(complastsuffix);
     zsfree(compiprefix);
     zsfree(compisuffix);
     zsfree(compqiprefix);
Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.52
diff -u -r1.52 complist.c
--- Src/Zle/complist.c	3 Jul 2002 07:59:59 -0000	1.52
+++ Src/Zle/complist.c	4 Jul 2002 09:22:27 -0000
@@ -1752,7 +1752,8 @@
 #define MAX_STATUS 128
 
 static char *
-setmstatus(char *status, int *csp, int *llp, int *lenp)
+setmstatus(char *status, char *sline, int sll, int scs,
+           int *csp, int *llp, int *lenp)
 {
     char *p, *s, *ret = NULL;
     int pl, sl, max;
@@ -1771,17 +1772,14 @@
         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;
+        cs = 0;
+        foredel(ll);
+        spaceinline(sll);
+        memcpy(line, sline, sll);
+        cs = scs;
     } else {
-        p = compprefix;
-        s = compsuffix;
+        p = complastprefix;
+        s = complastsuffix;
     }
     pl = strlen(p);
     sl = strlen(s);
@@ -1973,7 +1971,7 @@
             spaceinline(l);
             strncpy((char *) line, origline, l);
             cs = origcs;
-            setmstatus(status, NULL, NULL, NULL);
+            setmstatus(status, NULL, 0 , 0, NULL, NULL, NULL);
         } else if (strpfx("search", s)) {
             mode = (strstr(s, "back") ? MM_BSEARCH : MM_FSEARCH);
         }
@@ -2056,7 +2054,7 @@
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
         if (first) {
-            modeline = dyncat(compprefix, compsuffix);
+            modeline = dyncat(complastprefix, complastsuffix);
             modecs = cs;
             modell = ll;
             modelen = minfo.len;
@@ -2141,13 +2139,16 @@
                 spaceinline(l);
                 strncpy((char *) line, origline, l);
                 cs = origcs;
-                setmstatus(status, NULL, NULL, NULL);
+                setmstatus(status, NULL, 0, 0, NULL, NULL, NULL);
 
                 continue;
             }
 	} else if (cmd == Th(z_acceptandinfernexthistory) ||
                    (mode == MM_INTER && (cmd == Th(z_selfinsert) ||
                                          cmd == Th(z_selfinsertunmeta)))) {
+            char *saveline = NULL;
+            int savell;
+            int savecs;
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 
 	    s->prev = u;
@@ -2195,15 +2196,27 @@
                 else
                     selfinsertunmeta(zlenoargs);
 
+                saveline = (char *) zhalloc(ll);
+                memcpy(saveline, line, ll);
+                savell = ll;
+                savecs = cs;
                 iforcemenu = -1;
             } else
                 mode = 0;
 	    menucomplete(zlenoargs);
 	    iforcemenu = 0;
 
-	    if ((dat ? dat->num : nmatches) < 1 || !minfo.cur || !*(minfo.cur)) {
+            if (cmd != Th(z_acceptandinfernexthistory))
+                modeline = setmstatus(status, saveline, savell, savecs,
+                                      &modecs, &modell, &modelen);
+
+	    if (nmatches < 1 || !minfo.cur || !*(minfo.cur)) {
 		nolist = 1;
-		if ((dat ? (dat->nmesg || nmessages) : nmessages)) {
+                if (mode == MM_INTER) {
+                    statusline = status;
+                    statusll = strlen(status);
+                }
+		if (nmessages) {
 		    showinglist = -2;
 		    zrefresh();
 		} else {
@@ -2219,11 +2232,11 @@
 		    zrefresh();
 		    showinglist = clearlist = 0;
 		}
+                statusline = NULL;
+                statusll = 0;
+
 		goto getk;
 	    }
-            if (cmd != Th(z_acceptandinfernexthistory))
-                modeline = setmstatus(status, &modecs, &modell, &modelen);
-
 	    clearlist = listshown = 1;
 	    mselect = (*(minfo.cur))->gnum;
 	    setwish = wasnext = 1;

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
       [not found] ` <20020627182621.70670.qmail@web10405.mail.yahoo.com>
@ 2002-07-03  7:58   ` Sven Wischnowsky
  2002-07-04  9:27     ` Sven Wischnowsky
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-07-03  7:58 UTC (permalink / raw)
  To: Felix Rosencrantz, zsh-workers


You wrote:

> Here is a recipe, that causes a core dump for me:
> 
> host% autoload -U compinit; compinit -D
> host% zmodload zsh/complist
> host% bindkey "^Bm" menu-select
> host% bindkey "^Bi" vi-insert
> host% mkdir bug ; cd bug
> host% touch a b ba bb c
> host% more [^Bm]zsh: segmentation fault  $SHELL -f
> 
> I intended to do "^Bi" after "^Bm", since menu-select usually works for me.
> I've been seeing the problem with vi-insert.

(Sorry for the delay, Felix.)

Problem was that `dat' isn't set when the menu-select widget is called
(instead of calling menu selection via styles). This should fix it.


Bye
  Sven

Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.51
diff -u -r1.51 complist.c
--- Src/Zle/complist.c	26 Jun 2002 11:07:46 -0000	1.51
+++ Src/Zle/complist.c	3 Jul 2002 07:55:33 -0000
@@ -2201,9 +2201,9 @@
 	    menucomplete(zlenoargs);
 	    iforcemenu = 0;
 
-	    if (dat->num < 1 || !minfo.cur || !*(minfo.cur)) {
+	    if ((dat ? dat->num : nmatches) < 1 || !minfo.cur || !*(minfo.cur)) {
 		nolist = 1;
-		if (dat->nmesg || nmessages) {
+		if ((dat ? (dat->nmesg || nmessages) : nmessages)) {
 		    showinglist = -2;
 		    zrefresh();
 		} else {
@@ -2768,13 +2768,13 @@
     mselect = mlastcols = mlastlines = -1;
     mstatus = NULL;
     inselect = mhasstat = 0;
-    if (acc) {
+    if (acc && validlist && minfo.cur) {
 	menucmp = lastambig = hasoldlist = 0;
 	do_single(*(minfo.cur));
     }
     if (wasnext || broken) {
 	menucmp = 2;
-	showinglist = -2;
+	showinglist = (validlist ? -2 : 0);
 	minfo.asked = 0;
 	if (!noselect) {
 	    int nos = noselect;
@@ -2784,7 +2784,7 @@
 	}
     }
     if (!noselect && (!dat || acc)) {
-	showinglist = -2;
+	showinglist = (validlist ? -2 : 0);
 	onlyexpl = oe;
 	if (!smatches)
 	    clearlist = 1;

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-28  8:31 Sven Wischnowsky
  2002-05-28 10:44 ` Oliver Kiddle
  2002-05-28 12:08 ` Peter Stephenson
@ 2002-05-29 16:44 ` Felix Rosencrantz
  2 siblings, 0 replies; 21+ messages in thread
From: Felix Rosencrantz @ 2002-05-29 16:44 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

--- Sven Wischnowsky  wrote:
> I had been thinking about that, too, and, if it's going to be
> incremental searching -- which it should -- it's not entirely trivial
> to implement. ....
> 
> It makes completion be re-tried after every selfinsert-key. This is a
> bit like incremental searchin, only that the whole completion list
> changes to include only the set of possible matches.
> character into the line). And probably a way to set the default
> behaviour (i.e. when menu selection is first entered).

I frequently use the "history-incremental-search-backward" zle widget.
And I find that I would really like the power of matching control. (I
use completion with matching control even more frequently, so I've
started to type with pivot points in mind.)  So if I have history like:

	% mount_work read-only
	% cd /work
	% more README
	% cd /tmp
	% unmount_work

If I do a "history-incremental-search-backward" with "m_w", it would
find the "mount_work" command line if my matching spec makes the "_" a
pivot character.  (Likewise, "u_w" would find unmount_work, and "r-o"
would find the mount_work command.)

It seems like what you are suggesting will make something like
this possible.  I hope this incremental searching could be used in an
alternative widget to the "history-incremental-search-backward" widget,
but with matching control.

I think one of the other problems with trying to use completion for a
"history-incremental-search-backward" alternative, is the need of completion
to quote&blackslash multi-word completions.

-FR.


__________________________________________________
Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-29 11:23   ` Sven Wischnowsky
@ 2002-05-29 11:30     ` Peter Stephenson
  0 siblings, 0 replies; 21+ messages in thread
From: Peter Stephenson @ 2002-05-29 11:30 UTC (permalink / raw)
  To: Zsh hackers list

Sven Wischnowsky wrote:
> Hm, I can't reproduce this, but there'll be changes soon anyway, we'll
> see. I hadn't time yesterday.

I managed to show it with

 % zsh -f            
 % autoload -U compinit   
 % compinit -d
 % zstyle ':completion:*' format 'Completing %d'
 % zstyle ':completion:*' menu select=long select=5

and menu selection followed by interactive completion on a display with
at least two lines.  Maybe it's terminal specific; this is a Solaris
xterm.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-28 12:08 ` Peter Stephenson
@ 2002-05-29 11:23   ` Sven Wischnowsky
  2002-05-29 11:30     ` Peter Stephenson
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2002-05-29 11:23 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> This is fun, but there seems to be a buglet when I use menu selection
> with
> 
>   zstyle ':completion:*' format 'Completing %d'
> 
> and hit `return' to accept the completion; I get a display looking like
> 
>   % echo builds/pws_bc02/stack_unsigned.lst
> 
>   stack_unsigned.lst
>   stack_unsigned.lst
> 
> where the blank line was where the `interactive' prompt appeared, the
> upper filename where `Completing file' appeared, and the lower
> of the two filenames is still highlighted.

Hm, I can't reproduce this, but there'll be changes soon anyway, we'll
see. I hadn't time yesterday.


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-28  8:31 Sven Wischnowsky
  2002-05-28 10:44 ` Oliver Kiddle
@ 2002-05-28 12:08 ` Peter Stephenson
  2002-05-29 11:23   ` Sven Wischnowsky
  2002-05-29 16:44 ` Felix Rosencrantz
  2 siblings, 1 reply; 21+ messages in thread
From: Peter Stephenson @ 2002-05-28 12:08 UTC (permalink / raw)
  To: Zsh hackers list

Sven Wischnowsky wrote:

This is fun, but there seems to be a buglet when I use menu selection
with

  zstyle ':completion:*' format 'Completing %d'

and hit `return' to accept the completion; I get a display looking like

  % echo builds/pws_bc02/stack_unsigned.lst

  stack_unsigned.lst
  stack_unsigned.lst

where the blank line was where the `interactive' prompt appeared, the
upper filename where `Completing file' appeared, and the lower
of the two filenames is still highlighted.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-28 10:44 ` Oliver Kiddle
@ 2002-05-28 11:24   ` Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2002-05-28 11:24 UTC (permalink / raw)
  To: zsh-workers


Oliver Kiddle wrote:

> ...
> 
> It is an interesting idea. I'm not sure whether or not I'd use it
> or not. With this toggle key for the final patch, we might want to
> have a key which invokes this direct from the command line (as opposed
> to from menu selection).

Hm, yes, hadn't thought about that. (I hadn't thought much anyway, it
just occured to me how simple this is to implement ;-)

> Also, the interactive: prompt should perhaps
> be always displayed when this behaviour is active and not only after
> the first character is added. In fact, I think it would be better to
> use the real prompt for these characters or move the cursor down instead
> of using `[]'.

Yes, but this is problematic. We can't move the cursor into the
statusline (without changes to the zle display code). And on the
command line we have the currently inserted match. One might think
about messing with the command line buffer and restoring it when menu
selection is left, but that didn't seem like a good idea either.

Maybe we should make that modal, in the same way a incremental search
would be modal in menu selection. I.e., if this mode is selected, the
command line is changed to display the string as it is changed. A
non-inserting key would then leave this mode (again, as in isearch)
and display changes to the current match on the line and match
highlighting in the list again.

That would also make it more like isearch in general. It could
probably be viewed as a different kind of `isearch'.

> > Also, the behaviour of send-break (^G) after one has inserted some
> > more characters is arguable. Currently it leaves the additional
> > characters on the line. Maybe the line should go back to the state
> > when menu selection was entered. Or maybe a undo should remove all
> > characters added during menu selection.
> 
> I think the best would be if undo removed all the characters as you
> suggest and backspace could be used to do what undo currently does.
> It'd be nice if backspace worked that way regardless of what undo does.
> Additionally, tab might fill in any further characters common to all
> the remaining matches.

That would probably really look best with the changed command line
display. And, btw.:

  bindkey -M menuselect '^H' undo

works for me.


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Menu selection
  2002-05-28  8:31 Sven Wischnowsky
@ 2002-05-28 10:44 ` Oliver Kiddle
  2002-05-28 11:24   ` Sven Wischnowsky
  2002-05-28 12:08 ` Peter Stephenson
  2002-05-29 16:44 ` Felix Rosencrantz
  2 siblings, 1 reply; 21+ messages in thread
From: Oliver Kiddle @ 2002-05-28 10:44 UTC (permalink / raw)
  To: Zsh workers

On 28 May, Sven wrote:

> I can't find the message now, but Bart said that searching in menu
> selection would be nice to have. This patch doesn't do that, but...

Yes, something similar to history-incremental-search-forward/backward
might be useful (and I'd probably bind it to the same keys).

> It makes completion be re-tried after every selfinsert-key. This is a
> bit like incremental searchin, only that the whole completion list
> changes to include only the set of possible matches. As always, undo
> can be used to go back to previous lists. For easier testing, the
> patch makes every selfinsert-key show this behaviour unconditionally.
> In a final patch I think there should be a key to toggle between this
> behaviour and the usual one (leaving menu selection, inserting the
> character into the line). And probably a way to set the default
> behaviour (i.e. when menu selection is first entered).

It is an interesting idea. I'm not sure whether or not I'd use it
or not. With this toggle key for the final patch, we might want to
have a key which invokes this direct from the command line (as opposed
to from menu selection). Also, the interactive: prompt should perhaps
be always displayed when this behaviour is active and not only after
the first character is added. In fact, I think it would be better to
use the real prompt for these characters or move the cursor down instead
of using `[]'.

> Also, the behaviour of send-break (^G) after one has inserted some
> more characters is arguable. Currently it leaves the additional
> characters on the line. Maybe the line should go back to the state
> when menu selection was entered. Or maybe a undo should remove all
> characters added during menu selection.

I think the best would be if undo removed all the characters as you
suggest and backspace could be used to do what undo currently does.
It'd be nice if backspace worked that way regardless of what undo does.
Additionally, tab might fill in any further characters common to all
the remaining matches.

Oliver

This e-mail and any attachment is for authorised use by the intended recipient(s) only.  It may contain proprietary material, confidential information and/or be subject to legal privilege.  It should not be copied, disclosed to, retained or used by, any other party.  If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.  Thank you.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Menu selection
@ 2002-05-28  8:31 Sven Wischnowsky
  2002-05-28 10:44 ` Oliver Kiddle
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2002-05-28  8:31 UTC (permalink / raw)
  To: zsh-workers


Hi

I can't find the message now, but Bart said that searching in menu
selection would be nice to have. This patch doesn't do that, but...

I had been thinking about that, too, and, if it's going to be
incremental searching -- which it should -- it's not entirely trivial
to implement. The patch below (not committed and not to be committed
in its current form) is not intended to be a replacement for a patch
that implements searching in menu selection, but I think it's a nice
little patch (when improved to its final form).

It makes completion be re-tried after every selfinsert-key. This is a
bit like incremental searchin, only that the whole completion list
changes to include only the set of possible matches. As always, undo
can be used to go back to previous lists. For easier testing, the
patch makes every selfinsert-key show this behaviour unconditionally.
In a final patch I think there should be a key to toggle between this
behaviour and the usual one (leaving menu selection, inserting the
character into the line). And probably a way to set the default
behaviour (i.e. when menu selection is first entered).

Also, the behaviour of send-break (^G) after one has inserted some
more characters is arguable. Currently it leaves the additional
characters on the line. Maybe the line should go back to the state
when menu selection was entered. Or maybe a undo should remove all
characters added during menu selection.

And the output in the status line is a bit ugly. I think there should
be some visual feedback, though.

Anyway, what does everybody think? And do you have any suggestions
for the things I mentioned or any other ideas?


Bye
  Sven

diff -ur -r ../oz/Src/Zle/complist.c ./Src/Zle/complist.c
--- ../oz/Src/Zle/complist.c	Sun May 26 19:55:10 2002
+++ ./Src/Zle/complist.c	Mon May 27 22:59:51 2002
@@ -1711,8 +1711,11 @@
     Cmgroup amatches, pmatches, lastmatches, lastlmatches;
     char *origline;
     int origcs, origll;
+    char *status;
 };
 
+#define MAX_STATUS 128
+
 static int
 domenuselect(Hookdef dummy, Chdata dat)
 {
@@ -1725,7 +1728,9 @@
     int space, lbeg = 0, step = 1, wrap, pl = nlnct, broken = 0, first = 1;
     int nolist = 0;
     char *s;
+    char status[MAX_STATUS];
 
+    status[0] = '\0';
     queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
@@ -1822,7 +1827,16 @@
         if (first && !listshown && isset(LISTBEEP))
             zbeep();
         first = 0;
+        if (status[0]) {
+            statusline = status;
+            statusll = strlen(status);
+        } else {
+            statusline = NULL;
+            statusll = 0;
+        }
         zrefresh();
+        statusline = NULL;
+        statusll = 0;
         inselect = 1;
         if (noselect) {
             broken = 1;
@@ -1865,7 +1879,9 @@
 	} else if (cmd == Th(z_acceptline)) {
 	    acc = 1;
 	    break;
-	} else if (cmd == Th(z_acceptandinfernexthistory)) {
+	} else if (cmd == Th(z_acceptandinfernexthistory) ||
+                   cmd == Th(z_selfinsert) ||
+                   cmd == Th(z_selfinsertunmeta)) {
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 
 	    s->prev = u;
@@ -1888,6 +1904,7 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
 	    fixsuffix();
@@ -1897,9 +1914,45 @@
 	    invalidate_list();
 	    iforcemenu = 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);
+            }
 	    menucomplete(zlenoargs);
 	    iforcemenu = 0;
 
+            if (cmd != Th(z_acceptandinfernexthistory)) {
+                int pl = strlen(compprefix), sl = strlen(compsuffix);
+                int 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, compprefix + pl - h - 3);
+                    } else
+                        strcat(status, compprefix);
+
+                    strcat(status, "[]");
+                    if (sl > h - 3) {
+                        strncat(status, compsuffix, h - 3);
+                        strcat(status, "...");
+                    } else
+                        strcat(status, compsuffix);
+                }
+            }
 	    if (dat->num < 1 || !minfo.cur || !*(minfo.cur)) {
 		nolist = 1;
 		if (dat->nmesg || nmessages) {
@@ -1949,6 +2002,7 @@
 	    s->origline = origline;
 	    s->origcs = origcs;
 	    s->origll = origll;
+            s->status = dupstring(status);
 	    accept_last();
 	    handleundo();
 	    comprecursive = 1;
@@ -2013,6 +2067,7 @@
 	    origline = u->origline;
 	    origcs = u->origcs;
 	    origll = u->origll;
+            strcpy(status, u->status);
 
 	    u = u->prev;
 	    clearlist = 1;

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2002-07-30  7:46 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-18  7:57 Menu selection Sven Wischnowsky
2002-06-18  9:51 ` Oliver Kiddle
2002-06-19  7:49   ` Sven Wischnowsky
2002-06-20 15:52     ` Oliver Kiddle
2002-06-20 15:58       ` Bart Schaefer
2002-06-20 16:22         ` Oliver Kiddle
2002-06-21  9:27       ` Sven Wischnowsky
2002-06-26 10:18         ` Sven Wischnowsky
     [not found] <15642.49846.468542.689062@wischnow.berkom.de>
     [not found] ` <20020627182621.70670.qmail@web10405.mail.yahoo.com>
2002-07-03  7:58   ` Sven Wischnowsky
2002-07-04  9:27     ` Sven Wischnowsky
2002-07-04 17:56       ` Felix Rosencrantz
2002-07-05  8:09         ` Sven Wischnowsky
2002-07-24 23:01           ` Felix Rosencrantz
2002-07-30  7:47             ` Sven Wischnowsky
  -- strict thread matches above, loose matches on Subject: below --
2002-05-28  8:31 Sven Wischnowsky
2002-05-28 10:44 ` Oliver Kiddle
2002-05-28 11:24   ` Sven Wischnowsky
2002-05-28 12:08 ` Peter Stephenson
2002-05-29 11:23   ` Sven Wischnowsky
2002-05-29 11:30     ` Peter Stephenson
2002-05-29 16:44 ` Felix Rosencrantz

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).