about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Src/Zle/comp.h18
-rw-r--r--Src/Zle/complist.c22
-rw-r--r--Src/Zle/zle_tricky.c198
3 files changed, 173 insertions, 65 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index e32a969f3..201469872 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -239,13 +239,14 @@ struct cmatch {
     int gnum;			/* global number */
 };
 
-#define CMF_FILE      1		/* this is a file */
-#define CMF_REMOVE    2		/* remove the suffix */
-#define CMF_ISPAR     4		/* is paramter expansion */
-#define CMF_PARBR     8		/* paramter expansion with a brace */
-#define CMF_PARNEST  16		/* nested paramter expansion */
-#define CMF_NOLIST   32		/* should not be listed */
-#define CMF_DISPLINE 64		/* display strings one per line */
+#define CMF_FILE       1	/* this is a file */
+#define CMF_REMOVE     2	/* remove the suffix */
+#define CMF_ISPAR      4	/* is paramter expansion */
+#define CMF_PARBR      8	/* paramter expansion with a brace */
+#define CMF_PARNEST   16	/* nested paramter expansion */
+#define CMF_NOLIST    32	/* should not be listed */
+#define CMF_DISPLINE  64	/* display strings one per line */
+#define CMF_HIDE     128	/* temporarily hide this one */
 
 /* Stuff for completion matcher control. */
 
@@ -297,6 +298,8 @@ struct menuinfo {
     int we;			/* non-zero if the cursor was at the end */
     int insc;			/* length of suffix inserted */
     int asked;			/* we asked if the list should be shown */
+    char *prebr;		/* prefix before a brace, if any */
+    char *postbr;		/* suffix after a brace */
 };
 
 /* Flags for compadd and addmatches(). */
@@ -342,6 +345,7 @@ typedef struct cldata *Cldata;
 struct cldata {
     int columns;		/* screen width */
     int lines;			/* screen height */
+    int menuacc;		/* value of global menuacc */
     int valid;			/* no need to calculate anew */
     int nlist;			/* number of matches to list */
     int nlines;			/* number of lines needed */
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 7441db15f..a62a6df48 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -346,11 +346,12 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
 
 	    mtab[mm] = mp;
 	    mgtab[mm] = g;
-	    mmtabp = mtab + mm;
-	    mgtabp = mgtab + mm;
 	}
 	if (m->gnum == mselect) {
+	    int mm = (mcols * ml) + (mcols >> 1);
 	    mline = ml;
+	    mmtabp = mtab + mm;
+	    mgtabp = mgtab + mm;
 	    cc = COL_MA;
 	} else
 	    cc = COL_NO;
@@ -377,12 +378,14 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
 
 	    mtab[mx + mm] = mp;
 	    mgtab[mx + mm] = g;
-	    mmtabp = mtab + mx + mm;
-	    mgtabp = mgtab + mx + mm;
 	}
 	if (m->gnum == mselect) {
+	    int mm = mcols * ml;
+
 	    mcol = mx;
 	    mline = ml;
+	    mmtabp = mtab + mx + mm;
+	    mgtabp = mgtab + mx + mm;
 	    zcputs(&mcolors, COL_MA);
 	} else if (buf)
 	    putcolstr(&mcolors, path, buf->st_mode);
@@ -514,6 +517,8 @@ typedef struct menustack *Menustack;
 struct menustack {
     Menustack prev;
     char *line;
+    char *brbeg;
+    char *brend;
     int cs, acc;
     struct menuinfo info;
     Cmgroup amatches, pmatches, lmatches;
@@ -559,6 +564,7 @@ domenuselect(Hookdef dummy, Chdata dat)
 	}
 	p = mmtabp;
 	pg = mgtabp;
+	minfo.cur = *p;
 
     getk:
 
@@ -579,6 +585,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    s->pmatches = pmatches;
 	    s->lmatches = lmatches;
 	    s->acc = menuacc;
+	    s->brbeg = dupstring(brbeg);
+	    s->brend = dupstring(brend);
 	    menucmp = menuacc = 0;
 	    fixsuffix();
 	    validlist = 0;
@@ -604,6 +612,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
 	    s->amatches = s->pmatches = s->lmatches = NULL;
 	    s->acc = menuacc;
+	    s->brbeg = dupstring(brbeg);
+	    s->brend = dupstring(brend);
 	    acceptlast();
 	    do_menucmp(0);
 	    mselect = (*(minfo.cur))->gnum;
@@ -629,6 +639,10 @@ domenuselect(Hookdef dummy, Chdata dat)
 		lmatches = u->lmatches;
 		hasperm = 1;
 	    }
+	    zsfree(brbeg);
+	    zsfree(brend);
+	    brbeg = ztrdup(u->brbeg);
+	    brend = ztrdup(u->brend);
 	    u = u->prev;
 	    clearlist = 1;
 	} else if (cmd == Th(z_redisplay)) {
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 43cb2fe9f..e3b503265 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -112,6 +112,9 @@ static int movetoend;
 /**/
 int menucmp, menuacc;
 
+/**/
+static char *lastprebr, *lastpostbr;
+
 /* Information about menucompletion. */
 
 /**/
@@ -123,7 +126,9 @@ struct menuinfo minfo;
  * brpcs and brscs hold the positions of the re-inserted string in the    *
  * line.                                                                  */
 
-static char *brbeg = NULL, *brend = NULL;
+/**/
+char *brbeg = NULL, *brend = NULL;
+
 static int brpl, brsl, brpcs, brscs, qbrpl, qbrsl, hasunqu;
 
 /* The list of matches.  fmatches contains the matches we first ignore *
@@ -540,14 +545,17 @@ reversemenucomplete(char **args)
 	return menucomplete(args);
 
     HEAPALLOC {
-	if (minfo.cur == (minfo.group)->matches) {
-	    do {
-		if (!(minfo.group = (minfo.group)->prev))
-		    minfo.group = lmatches;
-	    } while (!(minfo.group)->mcount);
-	    minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1;
-	} else
-	    minfo.cur--;
+	do {
+	    if (minfo.cur == (minfo.group)->matches) {
+		do {
+		    if (!(minfo.group = (minfo.group)->prev))
+			minfo.group = lmatches;
+		} while (!(minfo.group)->mcount);
+		minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1;
+	    } else
+		minfo.cur--;
+	} while (menuacc &&
+		 !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
 	metafy_line();
 	do_single(*(minfo.cur));
 	unmetafy_line();
@@ -563,6 +571,15 @@ reversemenucomplete(char **args)
 void
 acceptlast(void)
 {
+    if (!menuacc) {
+	zsfree(minfo.prebr);
+	minfo.prebr = ztrdup(lastprebr);
+	zsfree(minfo.postbr);
+	minfo.postbr = ztrdup(lastpostbr);
+
+	if (listshown)
+	    showinglist = -2;
+    }
     menuacc++;
 
     if (brbeg && *brbeg) {
@@ -1140,13 +1157,16 @@ do_menucmp(int lst)
     }
     /* Otherwise go to the next match in the array... */
     HEAPALLOC {
-	if (!*++(minfo.cur)) {
-	    do {
-		if (!(minfo.group = (minfo.group)->next))
-		    minfo.group = amatches;
-	    } while (!(minfo.group)->mcount);
-	    minfo.cur = minfo.group->matches;
-	}
+	do {
+	    if (!*++(minfo.cur)) {
+		do {
+		    if (!(minfo.group = (minfo.group)->next))
+			minfo.group = amatches;
+		} while (!(minfo.group)->mcount);
+		minfo.cur = minfo.group->matches;
+	    }
+	} while (menuacc &&
+		 !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
 	/* ... and insert it into the command line. */
 	metafy_line();
 	do_single(*(minfo.cur));
@@ -7097,6 +7117,9 @@ invalidatelist(void)
 	listshown = 0;
     minfo.cur = NULL;
     minfo.asked = 0;
+    zsfree(minfo.prebr);
+    zsfree(minfo.postbr);
+    minfo.postbr = minfo.prebr = NULL;
     compwidget = NULL;
 }
 
@@ -7954,7 +7977,11 @@ unambig_data(int *cp)
 static int
 instmatch(Cmatch m, int *scs)
 {
-    int l, r = 0, ocs, a = cs;
+    int l, r = 0, ocs, a = cs, brb = 0;
+
+    zsfree(lastprebr);
+    zsfree(lastpostbr);
+    lastprebr = lastpostbr = NULL;
 
     /* Ignored prefix. */
     if (m->ipre) {
@@ -7980,6 +8007,9 @@ instmatch(Cmatch m, int *scs)
     /* Re-insert the brace beginning, if any. */
     if (brbeg && *brbeg) {
 	cs = a + m->brpl + (m->pre ? strlen(m->pre) : 0);
+	lastprebr = (char *) zalloc(cs - a + 1);
+	memcpy(lastprebr, (char *) line + a, cs - a);
+	lastprebr[cs - a] = '\0';
 	l = strlen(brbeg);
 	brpcs = cs;
 	inststrlen(brbeg, 1, l);
@@ -7999,12 +8029,14 @@ instmatch(Cmatch m, int *scs)
 	ocs = brscs = cs;
 	l = strlen(brend);
 	inststrlen(brend, 1, l);
+	brb = cs;
 	r += l;
 	cs = a + l;
     } else
 	brscs = -1;
     /* -S suffix */
-    *scs = cs;
+    if (scs)
+	*scs = cs;
     if (m->suf) {
 	inststrlen(m->suf, 1, (l = strlen(m->suf)));
 	r += l;
@@ -8014,12 +8046,56 @@ instmatch(Cmatch m, int *scs)
 	inststrlen(m->isuf, 1, (l = strlen(m->isuf)));
 	r += l;
     }
+    if (brend && *brend) {
+	lastpostbr = (char *) zalloc(cs - brb + 1);
+	memcpy(lastpostbr, (char *) line + brb, cs - brb);
+	lastpostbr[cs - brb] = '\0';
+    }
     lastend = cs;
     cs = ocs;
 
     return r;
 }
 
+/* Check if the match has the given prefix/suffix before/after the
+ * braces. */
+
+/**/
+int
+hasbrpsfx(Cmatch m, char *pre, char *suf)
+{
+    char *op = lastprebr, *os = lastpostbr;
+    VARARR(char, oline, ll);
+    int oll = ll, ocs = cs, ole = lastend, opcs = brpcs, oscs = brscs, ret;
+
+    memcpy(oline, line, ll);
+
+    lastprebr = lastpostbr = NULL;
+
+    instmatch(m, NULL);
+
+    cs = 0;
+    foredel(ll);
+    spaceinline(oll);
+    memcpy(line, oline, oll);
+    cs = ocs;
+    lastend = ole;
+    brpcs = opcs;
+    brscs = oscs;
+
+    ret = (((!op && !lastprebr) ||
+	    (op && lastprebr && !strcmp(op, lastprebr))) &&
+	   ((!os && !lastpostbr) ||
+	    (os && lastpostbr && !strcmp(os, lastpostbr))));
+
+    zsfree(lastprebr);
+    zsfree(lastpostbr);
+    lastprebr = op;
+    lastpostbr = os;
+
+    return ret;
+}
+
 /* Handle the case were we found more than one match. */
 
 /**/
@@ -8539,8 +8615,8 @@ printfmt(char *fmt, int n, int dopr, int doesc)
 Cmatch *
 skipnolist(Cmatch *p)
 {
-    while (*p && (((*p)->flags & CMF_NOLIST) ||
-		  ((*p)->disp && ((*p)->flags & CMF_DISPLINE))))
+    while (*p && (((*p)->flags & (CMF_NOLIST | CMF_HIDE)) ||
+		  ((*p)->disp && ((*p)->flags & (CMF_DISPLINE | CMF_HIDE)))))
 	p++;
 
     return p;
@@ -8579,7 +8655,8 @@ calclist(void)
     int max = 0, i;
     VARARR(int, mlens, nmatches + 1);
 
-    if (listdat.valid && lines == listdat.lines && columns == listdat.columns)
+    if (listdat.valid && menuacc == listdat.menuacc &&
+	lines == listdat.lines && columns == listdat.columns)
 	return;
 
     for (g = amatches; g; g = g->next) {
@@ -8625,6 +8702,12 @@ calclist(void)
 	    }
 	} else {
 	    for (p = g->matches; (m = *p); p++) {
+		if (menuacc && !hasbrpsfx(m, minfo.prebr, minfo.postbr)) {
+		    m->flags |= CMF_HIDE;
+		    continue;
+		}
+		m->flags &= ~CMF_HIDE;
+
 		if (m->disp) {
 		    if (m->flags & CMF_DISPLINE) {
 			nlines += 1 + printfmt(m->disp, 0, 0, 0);
@@ -8704,11 +8787,12 @@ calclist(void)
 		g->width = 0;
 
 		for (p = g->matches; (m = *p); p++)
-		    if (m->disp) {
-			if (!(m->flags & CMF_DISPLINE))
-			    glines += 1 + (mlens[m->gnum] / columns);
-		    } else if (!(m->flags & CMF_NOLIST))
-			glines += 1 + ((1 + mlens[m->gnum]) / columns);
+		    if (!(m->flags & CMF_HIDE))
+			if (m->disp) {
+			    if (!(m->flags & CMF_DISPLINE))
+				glines += 1 + (mlens[m->gnum] / columns);
+			} else if (!(m->flags & CMF_NOLIST))
+			    glines += 1 + ((1 + mlens[m->gnum]) / columns);
 	    }
 	}
 	g->lins = glines;
@@ -8737,7 +8821,8 @@ calclist(void)
 			int x, l = 0, v;
 
 			for (mm = columns / g->shortest; mm > g->cols; mm--) {
-			    for (j = i = ml = cl = l = v = x = 0,  k = g->dcount;
+			    for (j = i = ml = cl = l = v = x = 0,
+				     k = g->dcount;
 				 k > 0; k--) {
 				if (ylens[j] > ml)
 				    ml = ylens[j];
@@ -8754,7 +8839,7 @@ calclist(void)
 				    v = 0;
 				}
 			    }
-			    if (j < g->dcount) {
+			    if (j < yl) {
 				ws[x++] = ml;
 				cl += ml;
 			    }
@@ -8789,31 +8874,34 @@ calclist(void)
 	    } else if (g->width) {
 		if (isset(LISTROWSFIRST)) {
 		    int x, l = 0, v, al;
+		    Cmatch *q;
 
 		    for (mm = columns / g->shortest; mm > g->cols; mm--) {
-			for (j = i = ml = cl = l = v = x = 0,  k = g->dcount;
+			p = q = skipnolist(g->matches);
+			for (i = ml = cl = l = v = x = 0,  k = g->dcount;
 			     k > 0; k--) {
-			    m = g->matches[j];
-			    if (!(m->flags & (m->disp ? CMF_DISPLINE :
-					      CMF_NOLIST))) {
-				al = mlens[m->gnum] + add;
-				if (al > ml)
-				    ml = al;
-				j += mm;
-				v++;
-				if (j >= g->dcount) {
-				    if ((cl += ml) >= columns)
-					break;
-				    ws[x++] = ml;
-				    ml = 0;
-				    j = ++i;
-				    if (v > l)
-					l = v;
-				    v = 0;
-				}
+			    m = *p;
+			    al = mlens[m->gnum] + add;
+			    if (al > ml)
+				ml = al;
+			    for (j = mm; j && *p; j--)
+				p = skipnolist(p + 1);
+
+			    v++;
+			    if (!*p) {
+				if (v > l)
+				    l = v;
+				v = 0;
+
+				if ((cl += ml) >= columns)
+				    break;
+				ws[x++] = ml;
+				ml = 0;
+
+				p = q = skipnolist(q + 1);
 			    }
 			}
-			if (j < g->dcount) {
+			if (v) {
 			    ws[x++] = ml;
 			    cl += ml;
 			}
@@ -8829,8 +8917,9 @@ calclist(void)
 			 i < g->lins; i++) {
 			for (p = g->matches, j = k = cl = ml = mm = 0;
 			     (m = *p); p++, j++) {
-			    if (!(m->flags & (m->disp ? CMF_DISPLINE :
-					      CMF_NOLIST))) {
+			    if (!(m->flags &
+				  (m->disp ? (CMF_DISPLINE | CMF_HIDE) :
+				   (CMF_NOLIST | CMF_HIDE)))) {
 				al = mlens[m->gnum] + add;
 				if (al > ml)
 				    ml = al;
@@ -8858,11 +8947,11 @@ calclist(void)
 		nlines += i - g->lins;
 		g->lins = i;
 		g->cols = mm;
+		g->totl = cl;
+		cl -= add;
+		if (cl > max)
+		    max = cl;
 	    }
-	    g->totl = cl;
-	    cl -= add;
-	    if (cl > max)
-		max = cl;
 	}
 	for (g = amatches; g; g = g->next) {
 	    if (g->widths) {
@@ -8878,6 +8967,7 @@ calclist(void)
     listdat.hidden = hidden;
     listdat.nlist = nlist;
     listdat.nlines = nlines;
+    listdat.menuacc = menuacc;
 }
 
 /**/