about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/comp.h2
-rw-r--r--Src/Zle/compcore.c83
-rw-r--r--Src/Zle/complete.c5
-rw-r--r--Src/Zle/complist.c4
-rw-r--r--Src/Zle/compresult.c164
5 files changed, 195 insertions, 63 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index 57091c744..b18947064 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -124,6 +124,7 @@ struct cmatch {
 #define CMF_ROWS     (1<<10)	/* prefer LIST_ROWS_FIRST */
 #define CMF_MULT     (1<<11)	/* string appears more than once */
 #define CMF_FMULT    (1<<12)	/* first of multiple equal strings */
+#define CMF_ALL      (1<<13)	/* a match representing all other matches */
 
 /* Stuff for completion matcher control. */
 
@@ -236,6 +237,7 @@ struct menuinfo {
 #define CAF_UNIQALL 16
 #define CAF_ARRAYS  32
 #define CAF_KEYS    64
+#define CAF_ALL    128
 
 /* Data for compadd and addmatches() */
 
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 6941dbfe2..fa8104169 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -143,6 +143,11 @@ mod_export Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches;
 /**/
 mod_export int hasoldlist, hasperm;
 
+/* Non-zero if we have a match representing all other matches. */
+
+/**/
+int hasallmatch;
+
 /* Non-zero if we have newly added matches. */
 
 /**/
@@ -331,6 +336,7 @@ do_completion(Hookdef dummy, Compldat dat)
     maxmlen = -1;
     compignored = 0;
     nmessages = 0;
+    hasallmatch = 0;
 
     /* Make sure we have the completion list and compctl. */
     if (makecomplist(s, incmd, lst)) {
@@ -366,41 +372,8 @@ do_completion(Hookdef dummy, Compldat dat)
 	cs = origcs;
 	showinglist = -2;
     } else if (useline == 2 && nmatches > 1) {
-	int first = 1, nm = nmatches;
-	Cmatch *mc;
-
-	menucmp = 1;
-	menuacc = 0;
-
-	for (minfo.group = amatches;
-	     minfo.group && !(minfo.group)->mcount;
-	     minfo.group = (minfo.group)->next);
+	do_allmatches(1);
 
-	mc = (minfo.group)->matches;
-
-	while (1) {
-	    if (!first)
-		accept_last();
-	    first = 0;
-
-	    if (!--nm)
-		menucmp = 0;
-
-	    do_single(*mc);
-	    minfo.cur = mc;
-
-	    if (!*++(minfo.cur)) {
-		do {
-		    if (!(minfo.group = (minfo.group)->next))
-			break;
-		} while (!(minfo.group)->mcount);
-		if (!minfo.group)
-		    break;
-		minfo.cur = minfo.group->matches;
-	    }
-	    mc = minfo.cur;
-	}
-	menucmp = 0;
 	minfo.cur = NULL;
 
 	if (forcelist)
@@ -1604,7 +1577,7 @@ addmatches(Cadata dat, char **argv)
     Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl;
     Heap oldheap;
 
-    if (!*argv) {
+    if (!*argv && !(dat->aflags & CAF_ALL)) {
 	SWITCHHEAPS(oldheap, compheap) {
 	    /* Select the group in which to store the matches. */
 	    gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT  : 0) |
@@ -2042,6 +2015,36 @@ addmatches(Cadata dat, char **argv)
 	    set_list_array(dat->dpar, dparl);
 	if (dat->exp)
 	    addexpl();
+	if (!hasallmatch && (dat->aflags & CAF_ALL)) {
+	    Cmatch cm = (Cmatch) zhalloc(sizeof(struct cmatch));
+
+	    memset(cm, 0, sizeof(struct cmatch));
+	    cm->str = dupstring("<all>");
+	    cm->flags = (dat->flags | CMF_ALL |
+			 (complist ?
+			  ((strstr(complist, "packed") ? CMF_PACKED : 0) |
+			   (strstr(complist, "rows")   ? CMF_ROWS   : 0)) : 0));
+	    if (disp) {
+		if (!*++disp)
+		    disp = NULL;
+		if (disp)
+		    cm->disp = dupstring(*disp);
+	    } else {
+		cm->disp = dupstring("");
+		cm->flags |= CMF_DISPLINE;
+	    }
+	    mnum++;
+	    ainfo->count++;
+	    if (curexpl)
+		curexpl->count++;
+
+	    addlinknode(matches, cm);
+
+	    newmatches = 1;
+	    mgroup->new = 1;
+
+	    hasallmatch = 1;
+	}
     } SWITCHBACKHEAPS(oldheap);
 
     /* We switched back to the current heap, now restore the stack of
@@ -2695,7 +2698,7 @@ dupmatch(Cmatch m, int nbeg, int nend)
     r->pre = ztrdup(m->pre);
     r->suf = ztrdup(m->suf);
     r->flags = m->flags;
-    if (nbeg) {
+    if (m->brpl) {
 	int *p, *q, i;
 
 	r->brpl = (int *) zalloc(nbeg * sizeof(int));
@@ -2704,7 +2707,7 @@ dupmatch(Cmatch m, int nbeg, int nend)
 	    *p = *q;
     } else
 	r->brpl = NULL;
-    if (nend) {
+    if (m->brsl) {
 	int *p, *q, i;
 
 	r->brsl = (int *) zalloc(nend * sizeof(int));
@@ -2888,8 +2891,10 @@ freematch(Cmatch m, int nbeg, int nend)
     zsfree(m->remf);
     zsfree(m->disp);
     zsfree(m->autoq);
-    zfree(m->brpl, nbeg * sizeof(int));
-    zfree(m->brsl, nend * sizeof(int));
+    if (m->brpl)
+	zfree(m->brpl, nbeg * sizeof(int));
+    if (m->brsl)
+	zfree(m->brsl, nend * sizeof(int));
 
     zfree(m, sizeof(m));
 }
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 20da967ef..df9faed7a 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -452,6 +452,9 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 	    case 'Q':
 		dat.aflags |= CAF_QUOTE;
 		break;
+	    case 'C':
+		dat.aflags |= CAF_ALL;
+		break;
 	    case 'f':
 		dat.flags |= CMF_FILE;
 		break;
@@ -604,7 +607,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
  ca_args:
 
     if (!*argv && !dat.group && !dat.mesg &&
-	!(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON)))
+	!(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL)))
 	return 1;
 
     dat.match = match = cpcmatcher(match);
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index a7dbf6412..2334a2612 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -1375,6 +1375,10 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
 	return 0;
     }
     m = *mp;
+
+    if ((m->flags & CMF_ALL) && (!m->disp || !m->disp[0]))
+	bld_all_str(m);
+
     mlastm = m->gnum;
     if (m->disp && (m->flags & CMF_DISPLINE)) {
 	if (mselect >= 0) {
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index 924cf3dcd..cce06d1e3 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -570,36 +570,40 @@ instmatch(Cmatch m, int *scs)
 mod_export 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;
+    if (m->flags & CMF_ALL)
+	return 1;
+    else {
+	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);
+	memcpy(oline, line, ll);
 
-    lastprebr = lastpostbr = NULL;
+	lastprebr = lastpostbr = NULL;
 
-    instmatch(m, NULL);
+	instmatch(m, NULL);
 
-    cs = 0;
-    foredel(ll);
-    spaceinline(oll);
-    memcpy(line, oline, oll);
-    cs = ocs;
-    lastend = ole;
-    brpcs = opcs;
-    brscs = oscs;
+	cs = 0;
+	foredel(ll);
+	spaceinline(oll);
+	memcpy(line, oline, oll);
+	cs = ocs;
+	lastend = ole;
+	brpcs = opcs;
+	brscs = oscs;
 
-    ret = (((!pre && !lastprebr) ||
-	    (pre && lastprebr && !strcmp(pre, lastprebr))) &&
-	   ((!suf && !lastpostbr) ||
-	    (suf && lastpostbr && !strcmp(suf, lastpostbr))));
+	ret = (((!pre && !lastprebr) ||
+		(pre && lastprebr && !strcmp(pre, lastprebr))) &&
+	       ((!suf && !lastpostbr) ||
+		(suf && lastpostbr && !strcmp(suf, lastpostbr))));
 
-    zsfree(lastprebr);
-    zsfree(lastpostbr);
-    lastprebr = op;
-    lastpostbr = os;
+	zsfree(lastprebr);
+	zsfree(lastpostbr);
+	lastprebr = op;
+	lastpostbr = os;
 
-    return ret;
+	return ret;
+    }
 }
 
 /* Handle the case were we found more than one match. */
@@ -748,6 +752,65 @@ ztat(char *nam, struct stat *buf, int ls)
     }
 }
 
+/* Insert all matches in the command line. */
+
+/**/
+void
+do_allmatches(int end)
+{
+    int first = 1, nm = nmatches - 1, omc = menucmp, oma = menuacc, e;
+    Cmatch *mc;
+    struct menuinfo mi;
+    char *p = (brbeg ? ztrdup(lastbrbeg->str) : NULL);
+
+    memcpy(&mi, &minfo, sizeof(struct menuinfo));
+    menucmp = 1;
+    menuacc = 0;
+
+    for (minfo.group = amatches;
+	 minfo.group && !(minfo.group)->mcount;
+	 minfo.group = (minfo.group)->next);
+
+    mc = (minfo.group)->matches;
+
+    while (1) {
+	if (!((*mc)->flags & CMF_ALL)) {
+	    if (!first)
+		accept_last();
+	    first = 0;
+
+	    if (!omc && !--nm)
+		menucmp = 0;
+
+	    do_single(*mc);
+	}
+	minfo.cur = mc;
+
+	if (!*++(minfo.cur)) {
+	    do {
+		if (!(minfo.group = (minfo.group)->next))
+		    break;
+	    } while (!(minfo.group)->mcount);
+	    if (!minfo.group)
+		break;
+	    minfo.cur = minfo.group->matches;
+	}
+	mc = minfo.cur;
+    }
+    menucmp = omc;
+    menuacc = oma;
+
+    e = minfo.end;
+    memcpy(&minfo, &mi, sizeof(struct menuinfo));
+    minfo.end = e;
+    minfo.len = e - minfo.pos;
+
+    if (p) {
+	zsfree(lastbrbeg->str);
+	lastbrbeg->str = p;
+    }
+}
+
 /* Insert a single match in the command line. */
 
 /**/
@@ -785,6 +848,10 @@ do_single(Cmatch m)
     cs = minfo.pos;
     foredel(l);
 
+    if (m->flags & CMF_ALL)
+	do_allmatches(0);
+    else {
+
     /* And then we insert the new string. */
     minfo.len = instmatch(m, &scs);
     minfo.end = cs;
@@ -956,6 +1023,7 @@ do_single(Cmatch m)
 	runhookdef(INSERTMATCHHOOK, (void *) &dat);
 	minfo.cur = om;
     }
+    }
 }
 
 /* Do completion, given that we are in the middle of a menu completion.  We *
@@ -1886,6 +1954,54 @@ printlist(int over, CLPrintFunc printm, int showall)
 }
 
 /**/
+mod_export void
+bld_all_str(Cmatch all)
+{
+    Cmgroup g;
+    Cmatch *mp, m;
+    int len = columns - 5, t, add = 0;
+    VARARR(char, buf, columns + 1);
+
+    buf[0] = '\0';
+
+    for (g = amatches; g && !g->mcount; g = g->next);
+
+    mp = g->matches;
+    while (1) {
+	m = *mp;
+	if (!(m->flags & (CMF_ALL | CMF_HIDE)) && m->str) {
+	    t = strlen(m->str) + add;
+	    if (len >= t) {
+		if (add)
+		    strcat(buf, " ");
+		strcat(buf, m->str);
+		len -= t;
+		add = 1;
+	    } else {
+		if (len > add + 2) {
+		    if (add)
+			strcat(buf, " ");
+		    strncat(buf, m->str, len);
+		}
+		strcat(buf, " ...");
+		break;
+	    }
+	}
+	if (!*++mp) {
+	    do {
+		if (!(g = g->next))
+		    break;
+	    } while (!g->mcount);
+	    if (!g)
+		break;
+	    mp = g->matches;
+	}
+    }
+    zsfree(all->disp);
+    all->disp = ztrdup(buf);
+}
+
+/**/
 static void
 iprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
 	char *path, struct stat *buf)
@@ -1897,6 +2013,8 @@ iprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
 	return;
 
     m = *mp;
+    if ((m->flags & CMF_ALL) && (!m->disp || !m->disp[0]))
+	bld_all_str(m);
     if (m->disp) {
 	if (m->flags & CMF_DISPLINE) {
 	    printfmt(m->disp, 0, 1, 0);