about summary refs log tree commit diff
path: root/Src/Zle/complist.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle/complist.c')
-rw-r--r--Src/Zle/complist.c560
1 files changed, 166 insertions, 394 deletions
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 55e78c0cb..25fea68e1 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -317,434 +317,198 @@ putcolstr(Listcols c, char *n, mode_t m)
 static int noselect, mselect, inselect, mcol, mline, mcols, mlines;
 static Cmatch *mmatch, **mtab;
 static Cmgroup mgroup, *mgtab;
+static struct listcols mcolors;
 
-/* List the matches. Most of this is just taken from ilistmatches(),
- * of course. */
+
+static void
+clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width,
+	 char *path, struct stat *buf)
+{
+    Cmatch m;
+    int len, cc;
+
+    if (!mp) {
+	zcputs(&mcolors, COL_MI);
+	len = width - 2;
+	while (len-- > 0)
+	    putc(' ', shout);
+	if (mcolors.cols[COL_EC])
+	    tputs(mcolors.cols[COL_EC], 1, putshout);
+	else
+	    zcputs(&mcolors, COL_NO);
+
+	return;
+    }
+    m = *mp;
+    if (m->disp && (m->flags & CMF_DISPLINE)) {
+	if (mselect >= 0) {
+	    int mm = (mcols * ml) + (mcols >> 1);
+
+	    mtab[mm] = mp;
+	    mgtab[mm] = g;
+	}
+	if (m->gnum == mselect) {
+	    mline = ml;
+	    mmatch = mp;
+	    mgroup = g;
+	    cc = COL_MA;
+	} else
+	    cc = COL_NO;
+	zcputs(&mcolors, cc);
+	printfmt(m->disp, 0, 1, 0);
+	if (mcolors.cols[COL_EC])
+	    tputs(mcolors.cols[COL_EC], 1, putshout);
+	else
+	    zcputs(&mcolors, COL_NO);
+    } else {
+	int mx;
+
+	if (g->widths) {
+	    int i;
+
+	    for (i = mx = 0; i < mc; i++)
+		mx += g->widths[i];
+	} else
+	    mx = mc * g->width;
+	mx += (width >> 1);
+
+	if (mselect >= 0) {
+	    int mm = mcols * ml;
+
+	    mtab[mx + mm] = mp;
+	    mgtab[mx + mm] = g;
+	}
+	if (m->gnum == mselect) {
+	    mcol = mx;
+	    mline = ml;
+	    mmatch = mp;
+	    mgroup = g;
+	    zcputs(&mcolors, COL_MA);
+	} else if (buf)
+	    putcolstr(&mcolors, path, buf->st_mode);
+	else
+	    zcputs(&mcolors, COL_NO);
+
+	nicezputs((m->disp ? m->disp : m->str), shout);
+	len = niceztrlen(m->disp ? m->disp : m->str);
+
+	if (isset(LISTTYPES)) {
+	    if (buf)
+		putc(file_type(buf->st_mode), shout);
+	    else
+		putc(' ', shout);
+	    len++;
+	}
+	len = width - len - 2;
+
+	while (len-- > 0)
+	    putc(' ', shout);
+
+	if (mcolors.cols[COL_EC])
+	    tputs(mcolors.cols[COL_EC], 1, putshout);
+	else
+	    zcputs(&mcolors, COL_NO);
+	if (!lastc) {
+	    zcputs(&mcolors, COL_NO);
+	    fputs("  ", shout);
+	    if (mcolors.cols[COL_EC])
+		tputs(mcolors.cols[COL_EC], 1, putshout);
+	    else
+		zcputs(&mcolors, COL_NO);
+	}
+    }
+}
 
 static int
 complistmatches(Hookdef dummy, Chdata dat)
 {
-    Cmgroup amatches = dat->matches, g;
-    Cmatch *p, m;
-    Cexpl *e;
-    int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0;
-    int of = isset(LISTTYPES), cf;
-    int mc, ml = 0, cc, hasm = 0, cl = -1;
-    struct listcols col;
+    Cmgroup oamatches = amatches;
+
+    amatches = dat->matches;
 
     if (minfo.asked == 2) {
 	showinglist = 0;
+	amatches = oamatches;
 	return (noselect = 1);
     }
-    getcols(&col);
-
-    for (g = amatches; g; g = g->next) {
-	char **pp = g->ylist;
-	int nl = 0, l;
-
-	if (pp) {
-	    /* We have an ylist, lets see, if it contains newlines. */
-	    while (!nl && *pp)
-		nl = !!strchr(*pp++, '\n');
-
-	    pp = g->ylist;
-	    if (nl || !pp[1]) {
-		/* Yup, there are newlines, count lines. */
-		char *nlptr, *sptr;
-
-		g->flags |= CGF_LINES;
-		noselect = 1;
-		while ((sptr = *pp)) {
-		    while (sptr && *sptr) {
-			nlines += (nlptr = strchr(sptr, '\n'))
-			    ? 1 + (nlptr-sptr)/columns
-			    : strlen(sptr)/columns;
-			sptr = nlptr ? nlptr+1 : NULL;
-		    }
-		    nlines++;
-		    pp++;
-		}
-		nlines--;
-	    } else {
-		while (*pp) {
-		    if ((l = strlen(*pp)) > longest)
-			longest = l;
-		    nlist++;
-		    pp++;
-		}
-	    }
-	} else {
-	    for (p = g->matches; (m = *p); p++) {
-		if (m->disp) {
-		    if (m->flags & CMF_DISPLINE) {
-			nlines += 1 + printfmt(m->disp, 0, 0, 0);
-			g->flags |= CGF_HASDL;
-		    } else if ((l = niceztrlen(m->disp)) > longest)
-			longest = l;
-		    nlist++;
-		} else if (!(m->flags & CMF_NOLIST)) {
-		    if ((l = niceztrlen(m->str)) > longest)
-			longest = l;
-		    nlist++;
-		} else
-		    noselect = 1;
-	    }
-	}
-	if ((e = g->expls)) {
-	    while (*e) {
-		if ((*e)->count)
-		    nlines += 1 + printfmt((*e)->str, (*e)->count, 0, 1);
-		e++;
-	    }
-	}
-    }
-    longest += 2 + of;
-    if ((ncols = columns / longest)) {
-	for (g = amatches; g; g = g->next)
-	    nlines += (g->lcount - g->llcount + ncols - 1) / ncols;
-    } else {
-	ncols = 1;
-	opl = 1;
-	for (g = amatches; g; g = g->next) {
-	    char **pp = g->ylist;
-
-	    if (pp) {
-		if (!(g->flags & CGF_LINES)) {
-		    while (*pp) {
-			nlines += 1 + (strlen(*pp) / columns);
-			pp++;
-		    }
-		}
-	    } else
-		for (p = g->matches; (m = *p); p++)
-		    if (m->disp) {
-			if (m->flags & CMF_DISPLINE)
-			    nlines += 1 + printfmt(m->disp, 0, 0, 0);
-			else
-			    nlines += 1 + (niceztrlen(m->disp) / columns);
-		    } else if (!(m->flags & CMF_NOLIST))
-			nlines += 1 + ((1 + niceztrlen(m->str)) / columns);
-	}
-    }
-    cf = (isset(USEZLE) && !termflags && complastprompt && *complastprompt);
-    if (!nlines || (mselect >= 0 && (!cf || (nlines + nlnct - 1) >= lines))) {
+    getcols(&mcolors);
+
+    calclist();
+
+    if (!listdat.nlines || (mselect >= 0 &&
+			    (!(isset(USEZLE) && !termflags &&
+			       complastprompt && *complastprompt) ||
+			     (listdat.nlines + nlnct - 1) >= lines))) {
 	showinglist = listshown = 0;
 	noselect = 1;
+	amatches = oamatches;
 	return 1;
     }
-    /* Set the cursor below the prompt. */
+    if (listdat.hidden) {
+	noselect = 1;
+	mselect = -1;
+    }
     if (inselect)
 	clearflag = 0;
-    trashzle();
-    showinglist = listshown = 0;
-
-    clearflag = cf;
-
-    /* Maybe we have to ask if the user wants to see the list. */
-    if ((!minfo.cur || !minfo.asked) &&
-	((complistmax && nlist > complistmax) ||
-	 (!complistmax && nlines >= lines))) {
-	int qup;
-	zsetterm();
-	qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1, 1);
-	fflush(shout);
-	if (getzlequery() != 'y') {
-	    if (clearflag) {
-		putc('\r', shout);
-		tcmultout(TCUP, TCMULTUP, qup);
-		if (tccan(TCCLEAREOD))
-		    tcout(TCCLEAREOD);
-		tcmultout(TCUP, TCMULTUP, nlnct);
-	    } else
-		putc('\n', shout);
-	    noselect = 1;
-	    if (minfo.cur)
-		minfo.asked = 2;
-	    return 1;
-	}
-	if (clearflag) {
-	    putc('\r', shout);
-	    tcmultout(TCUP, TCMULTUP, qup);
-	    if (tccan(TCCLEAREOD))
-		tcout(TCCLEAREOD);
-	} else
-	    putc('\n', shout);
-	settyinfo(&shttyinfo);
-	if (minfo.cur)
-	    minfo.asked = 1;
+
+    if (asklist()) {
+	amatches = oamatches;
+	return 1;
     }
     if (mselect >= 0) {
 	int i;
 
-	i = ncols * nlines;
+	i = columns * listdat.nlines;
 	free(mtab);
 	mtab = (Cmatch **) zalloc(i * sizeof(Cmatch **));
 	memset(mtab, 0, i * sizeof(Cmatch **));
 	free(mgtab);
 	mgtab = (Cmgroup *) zalloc(i * sizeof(Cmgroup));
 	memset(mgtab, 0, i * sizeof(Cmgroup));
-	mcols = ncols;
-	mlines = cl = nlines;
-	if (cl < 2) {
-	    cl = -1;
-	    if (tccan(TCCLEAREOD))
-		tcout(TCCLEAREOD);
-	}
+	mcols = columns;
+	mlines = listdat.nlines;
     }
-    /* Now print the matches. */
     last_col = COL_NO - 1;
-    g = amatches;
-    while (g) {
-	char **pp = g->ylist;
 
-	if ((e = g->expls)) {
-	    int l;
-
-	    while (*e) {
-		if ((*e)->count) {
-		    if (pnl) {
-			putc('\n', shout);
-			pnl = 0;
-			ml++;
-			if (cl >= 0 && --cl <= 1) {
-			    cl = -1;
-			    if (tccan(TCCLEAREOD))
-				tcout(TCCLEAREOD);
-			}
-		    }
-		    l = printfmt((*e)->str, (*e)->count, 1, 1);
-		    ml += l;
-		    if (cl >= 0 && (cl -= l) <= 1) {
-			cl = -1;
-			if (tccan(TCCLEAREOD))
-			    tcout(TCCLEAREOD);
-		    }
-		    pnl = 1;
-		}
-		e++;
-	    }
-	}
-	if (pp && *pp) {
-	    if (pnl) {
-		putc('\n', shout);
-		pnl = 0;
-		ml++;
-		if (cl >= 0 && --cl <= 1) {
-		    cl = -1;
-		    if (tccan(TCCLEAREOD))
-			tcout(TCCLEAREOD);
-		}
-	    }
-	    if (g->flags & CGF_LINES) {
-		while (*pp) {
-		    zputs(*pp, shout);
-		    if (*++pp)
-			putc('\n', shout);
-		}
-	    } else {
-		int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, a;
-		char **pq;
-
-		while (n && nl--) {
-		    i = ncols;
-		    mc = 0;
-		    pq = pp;
-		    while (n && i--) {
-			if (pq - g->ylist >= g->lcount)
-			    break;
-			zputs(*pq, shout);
-			if (i) {
-			    a = longest - strlen(*pq);
-			    while (a--)
-				putc(' ', shout);
-			}
-			pq += nc;
-			n--;
-		    }
-		    if (n) {
-			putc('\n', shout);
-			ml++;
-			if (cl >= 0 && --cl <= 1) {
-			    cl = -1;
-			    if (tccan(TCCLEAREOD))
-				tcout(TCCLEAREOD);
-			}
-		    }
-		    pp++;
-		}
-	    }
-	} else if (g->lcount) {
-	    int n = g->lcount - g->llcount, nl = (n + ncols - 1) / ncols;
-	    int nc = nl, i, j, a = 0;
-	    int zt;
-	    Cmatch *q;
-
-	    if (g->flags & CGF_HASDL) {
-		for (p = g->matches; (m = *p); p++)
-		    if (m->disp && (m->flags & CMF_DISPLINE)) {
-			if (pnl) {
-			    putc('\n', shout);
-			    pnl = 0;
-			    ml++;
-			    if (cl >= 0 && --cl <= 1) {
-				cl = -1;
-				if (tccan(TCCLEAREOD))
-				    tcout(TCCLEAREOD);
-			    }
-			}
-			hasm = 1;
-			if (mselect >= 0) {
-			    for (i = 0; i < ncols; i++) {
-				mtab[i + (ncols * ml)] = p;
-				mgtab[i + (ncols * ml)] = g;
-			    }
-			}
-			if (m->gnum == mselect) {
-			    mline = ml;
-			    mmatch = p;
-			    mgroup = g;
-			    cc = COL_MA;
-			} else
-			    cc = COL_NO;
-			zcputs(&col, cc);
-			printfmt(m->disp, 0, 1, 0);
-			if (col.cols[COL_EC])
-			    tputs(col.cols[COL_EC], 1, putshout);
-			else
-			    zcputs(&col, COL_NO);
-			pnl = 1;
-		    }
-	    }
-	    if (n && pnl) {
-		putc('\n', shout);
-		pnl = 0;
-		ml++;
-		if (cl >= 0 && --cl <= 1) {
-		    cl = -1;
-		    if (tccan(TCCLEAREOD))
-			tcout(TCCLEAREOD);
-		}
-	    }
-	    for (p = skipnolist(g->matches); n && nl--;) {
-		i = ncols;
-		mc = 0;
-		q = p;
-		while (n && i--) {
-		    if (!(m = *q)) {
-			zcputs(&col, COL_MI);
-			a = longest - 2;
-			while (a--)
-			    putc(' ', shout);
-			if (col.cols[COL_EC])
-			    tputs(col.cols[COL_EC], 1, putshout);
-			else
-			    zcputs(&col, COL_NO);
-			break;
-		    }
-		    hasm = 1;
-		    if (mselect >= 0) {
-			mtab[mc + (ncols * ml)] = q;
-			mgtab[mc + (ncols * ml)] = g;
-		    }
-		    if (m->gnum == mselect) {
-			mcol = mc;
-			mline = ml;
-			mmatch = q;
-			mgroup = g;
-			cc = COL_MA;
-		    } else
-			cc = -1;
-		    if (!m->disp && m->flags & CMF_FILE) {
-			struct stat buf;
-			char *pb;
-
-			pb = (char *) zhalloc((m->prpre ? strlen(m->prpre) : 0) +
-					     3 + strlen(m->str));
-			sprintf(pb, "%s%s", (m->prpre ? m->prpre : "./"),
-				m->str);
-
-			zt = ztat(pb, &buf, 1);
-			if (cc >= 0)
-			    zcputs(&col, cc);
-			else if (zt)
-			    zcputs(&col, COL_NO);
-			else
-			    putcolstr(&col, pb, buf.st_mode);
-			nicezputs(m->str, shout);
-			if (zt)
-			    putc(' ', shout);
-			else
-			    putc(file_type(buf.st_mode), shout);
-		    } else {
-			zcputs(&col, cc >= 0 ? cc : COL_NO);
-			nicezputs((m->disp ? m->disp : m->str), shout);
-			if (of)
-			    putc(' ', shout);
-		    }
-		    a = longest - niceztrlen(m->disp ? m->disp : m->str) - 2 - of;
-		    while (a-- > 0)
-			putc(' ', shout);
-		    if (col.cols[COL_EC])
-			tputs(col.cols[COL_EC], 1, putshout);
-		    else
-			zcputs(&col, COL_NO);
-		    if (i) {
-			zcputs(&col, COL_NO);
-			fputs("  ", shout);
-			if (col.cols[COL_EC])
-			    tputs(col.cols[COL_EC], 1, putshout);
-			else
-			    zcputs(&col, COL_NO);
-		    }
-		    if (--n)
-			for (j = nc; j && *q; j--)
-			    q = skipnolist(q + 1);
-		    mc++;
-		}
-		if (i > 0) {
-		    zcputs(&col, COL_MI);
-		    a = longest - 2;
-		    while (a--)
-			putc(' ', shout);
-		    if (col.cols[COL_EC])
-			tputs(col.cols[COL_EC], 1, putshout);
-		    else
-			zcputs(&col, COL_NO);
-		}
-		if (n) {
-		    putc('\n', shout);
-		    ml++;
-		    if (cl >= 0 && --cl <= 1) {
-			cl = -1;
-			if (tccan(TCCLEAREOD))
-			    tcout(TCCLEAREOD);
-		    }
-		    if (n && nl)
-			p = skipnolist(p + 1);
-		}
-	    }
-	}
-	if (g->lcount)
-	    pnl = 1;
-	g = g->next;
-    }
-    if (clearflag) {
-	/* Move the cursor up to the prompt, if always_last_prompt *
-	 * is set and all that...                                  */
-	if ((nlines += nlnct - 1) < lines) {
-	    tcmultout(TCUP, TCMULTUP, nlines);
-	    showinglist = -1;
-	} else
-	    clearflag = 0, putc('\n', shout);
-    } else
-	putc('\n', shout);
-    listshown = (clearflag ? 1 : -1);
-    if (!hasm || nlines >= lines)
+    if (!printlist(1, clprintm) || listdat.nlines >= lines)
 	noselect = 1;
 
+    amatches = oamatches;
+
     return noselect;
 }
 
+static int
+adjust_mcol(Cmatch ***tabp, Cmgroup **grp)
+{
+    Cmatch **tab = *tabp;
+    int p, n, c;
+
+    tab -= mcol;
+
+    for (p = mcol; p >= 0 && !tab[p]; p--);
+    for (n = mcol; n < mcols && !tab[n]; n++);
+    if (n == mcols)
+	n = -1;
+
+    if (p < 0) {
+	if (n < 0)
+	    return 1;
+	c = n;
+    } else if (n < 0)
+	c = p;
+    else
+	c = ((mcol - p) < (n - mcol) ? p : n);
+
+    *tabp = tab + c;
+    if (grp)
+	*grp = *grp + c - mcol;
+
+    mcol = c;
+    
+    return 0;
+}
+
 typedef struct menustack *Menustack;
 
 struct menustack {
@@ -887,6 +651,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 		    mline++;
 		    p += mcols;
 		}
+		if (adjust_mcol(&p, NULL))
+		    continue;
 	    } while (!*p);
 	} else if (cmd == Th(z_uphistory) ||
 		   cmd == Th(z_uplineorhistory) ||
@@ -900,6 +666,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 		    mline--;
 		    p -= mcols;
 		}
+		if (adjust_mcol(&p, NULL))
+		    continue;
 	    } while (!*p);
 	} else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) {
 	    do {
@@ -958,6 +726,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 		    p += mcols;
 		    pg += mcols;
 		}
+		if (adjust_mcol(&p, &pg))
+		    continue;
 	    } while (ol != mline && (*pg == g || !*pg));
 	} else if (cmd == Th(z_backwardword) ||
 		   cmd == Th(z_emacsbackwardword) ||
@@ -975,6 +745,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 		    p -= mcols;
 		    pg -= mcols;
 		}
+		if (adjust_mcol(&p, &pg))
+		    continue;
 	    } while (ol != mline && (*pg == g || !*pg));
 	} else if (cmd == Th(z_completeword) ||
 		   cmd == Th(z_expandorcomplete) ||