Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Patch available for 3.0.6-pre-5



I wrote:

> [ ... collist ... ]

This one is even weirder... (if memory serves, Peter once talked about 
this).

It adds:
- the `ma' capability to collist; it is used during menucompletion to
  highlight the match inserted (note that you still have to set
  `ZLS_COLO(|U)RS' to see this -- an empty string will suffice)
- the `menu-select' widget which is a bit like `menu-complete' but
  displays the list and then lets you use cursor-movement keys to
  navigate in the list; to return to line editing, you can use
  `accept-line' or `send-break'; `accept-and-hold' leaves the match
  inserted in place and continues selecting matches from the list
  (i.e. it's like `accept-and-menu-complete')

Dunno if this is interesting to anyone, so I haven't written a manual
for this. (sorry :-}

Bye
 Sven

diff -u -r oos/Zle/collist.c Src/Zle/collist.c
--- oos/Zle/collist.c	Mon Jun 21 11:07:11 1999
+++ Src/Zle/collist.c	Mon Jun 21 11:32:27 1999
@@ -30,6 +30,8 @@
 #include "collist.mdh"
 #include "collist.pro"
 
+static Widget w_menuselect;
+
 /* We use the parameters ZLS_COLORS and ZLS_COLOURS in the same way as
  * the color ls does. It's just that we don't support the `or' file
  * type. */
@@ -50,21 +52,22 @@
 #define COL_LC 10
 #define COL_RC 11
 #define COL_EC 12
+#define COL_MA 13
 
-#define NUM_COLS 13
+#define NUM_COLS 14
 
 /* Names of the terminal strings. */
 
 static char *colnames[] = {
     "no", "fi", "di", "ln", "pi", "so", "bd", "cd", "ex", "mi",
-    "lc", "rc", "ec", NULL
+    "lc", "rc", "ec", "ma", NULL
 };
 
 /* Default values. */
 
 static char *defcols[] = {
     "0", "0", "32", "36", "31", "33", "44;37", "44;37", "35", NULL,
-    "\033[", "m", NULL
+    "\033[", "m", NULL, "7"
 };
 
 /* This describes a terminal string for a filename extension. */
@@ -200,9 +203,13 @@
     int i;
 
     if (!(s = getsparam("ZLS_COLORS")) &&
-	!(s = getsparam("ZLS_COLOURS")))
+	!(s = getsparam("ZLS_COLOURS"))) {
+	for (i = 0; i < NUM_COLS; i++)
+	    c->cols[i] = "";
+	
+	c->exts = NULL;
 	return 1;
-
+    }
     /* We have one of the parameters, use it. */
     memset(c, 0, sizeof(*c));
     s = dupstring(s);
@@ -216,6 +223,7 @@
     /* Default for missing files. */
     if (!c->cols[COL_MI])
 	c->cols[COL_MI] = c->cols[COL_FI];
+
     if (!c->cols[COL_EC]) {
 	char *e = (char *) zhalloc(strlen(c->cols[COL_LC]) +
 				   strlen(c->cols[COL_NO]) +
@@ -260,21 +268,27 @@
     return c->cols[COL_FI];
 }
 
+/* Information about the list shown. */
+
+static int noselect, mselect, mcol, mline, mcols, mlines;
+static Cmatch *mmatch, **mtab;
+static Cmgroup mgroup, *mgtab;
+
 /* List the matches. Most of this is just taken from ilistmatches(),
  * of course. */
 
-static int
-collistmatches(Hookdef dummy, Cmgroup amatches)
+static void
+icollistmatches(Cmgroup amatches, int mark)
 {
     Cmgroup g;
     Cmatch *p, m;
     Cexpl *e;
     int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0;
     int of = isset(LISTTYPES);
+    int mc, ml = 0, cc;
     struct listcols col;
 
-    if (getcols(&col))
-	return ilistmatches(dummy, amatches);
+    getcols(&col);
 
     /* Set the cursor below the prompt. */
     trashzle();
@@ -298,7 +312,7 @@
 		char *nlptr, *sptr;
 
 		g->flags |= CGF_LINES;
-		
+		noselect = 1;
 		while ((sptr = *pp)) {
 		    while (sptr && *sptr) {
 			nlines += (nlptr = strchr(sptr, '\n'))
@@ -363,6 +377,7 @@
     if ((complistmax && nlist > complistmax) ||
 	(!complistmax && nlines >= lines)) {
 	int qup;
+	noselect = 1;
 	zsetterm();
 	qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1);
 	fflush(shout);
@@ -375,7 +390,6 @@
 		tcmultout(TCUP, TCMULTUP, nlnct);
 	    } else
 		putc('\n', shout);
-	    return 0;
 	}
 	if (clearflag) {
 	    putc('\r', shout);
@@ -386,7 +400,20 @@
 	    putc('\n', shout);
 	settyinfo(&shttyinfo);
     }
+    if (mselect >= 0) {
+	int i;
 
+	mark = mselect;
+	i = ncols * 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 = nlines;
+    }
     /* Now print the matches. */
     g = amatches;
     while (g) {
@@ -398,8 +425,9 @@
 		    if (pnl) {
 			putc('\n', shout);
 			pnl = 0;
+			ml++;
 		    }
-		    printfmt((*e)->str, (*e)->count, 1);
+		    ml += printfmt((*e)->str, (*e)->count, 1);
 		    pnl = 1;
 		}
 		e++;
@@ -409,6 +437,7 @@
 	    if (pnl) {
 		putc('\n', shout);
 		pnl = 0;
+		ml++;
 	    }
 	    if (g->flags & CGF_LINES) {
 		while (*pp) {
@@ -422,6 +451,7 @@
 
 		while (n && nl--) {
 		    i = ncols;
+		    mc = 0;
 		    pq = pp;
 		    while (n && i--) {
 			if (pq - g->ylist >= g->lcount)
@@ -435,8 +465,10 @@
 			pq += nc;
 			n--;
 		    }
-		    if (n)
+		    if (n) {
 			putc('\n', shout);
+			ml++;
+		    }
 		    pp++;
 		}
 	    }
@@ -448,9 +480,11 @@
 	    if (n && pnl) {
 		putc('\n', shout);
 		pnl = 0;
+		ml++;
 	    }
 	    for (p = skipnolist(g->matches); n && nl--;) {
 		i = ncols;
+		mc = 0;
 		q = p;
 		while (n && i--) {
 		    fputs(col.cols[COL_LC], shout);
@@ -463,6 +497,18 @@
 			fputs(col.cols[COL_EC], shout);
 			break;
 		    }
+		    if (mselect >= 0) {
+			mtab[mc + (ncols * ml)] = q;
+			mgtab[mc + (ncols * ml)] = g;
+		    }
+		    if (m->gnum == mark) {
+			mcol = mc;
+			mline = ml;
+			mmatch = q;
+			mgroup = g;
+			cc = COL_MA;
+		    } else
+			cc = -1;
 		    if (m->flags & CMF_FILE) {
 			struct stat buf;
 			char *pb;
@@ -472,7 +518,10 @@
 			sprintf(pb, "%s%s", (m->prpre ? m->prpre : "./"),
 				m->str);
 
-			if ((zt = ztat(pb, &buf, 1)))
+			zt = ztat(pb, &buf, 1);
+			if (cc >= 0)
+			    fputs(col.cols[cc], shout);
+			else if (zt)
 			    fputs(col.cols[COL_NO], shout);
 			else
 			    fputs(getcolstr(&col, pb, buf.st_mode), shout);
@@ -483,7 +532,7 @@
 			else
 			    putc(file_type(buf.st_mode), shout);
 		    } else {
-			fputs(col.cols[COL_NO], shout);
+			fputs(col.cols[cc >= 0 ? cc : COL_NO], shout);
 			fputs(col.cols[COL_RC], shout);
 			nicezputs(m->str, shout);
 			if (of)
@@ -503,6 +552,7 @@
 		    if (--n)
 			for (j = nc; j && *q; j--)
 			    q = skipnolist(q + 1);
+		    mc++;
 		}
 		if (i > 0) {
 		    fputs(col.cols[COL_LC], shout);
@@ -515,6 +565,7 @@
 		}
 		if (n) {
 		    putc('\n', shout);
+		    ml++;
 		    if (n && nl)
 			p = skipnolist(p + 1);
 		}
@@ -536,6 +587,179 @@
 	    clearflag = 0, putc('\n', shout);
     } else
 	putc('\n', shout);
+}
+
+static int
+collistmatches(Hookdef dummy, Cmgroup amatches)
+{
+    icollistmatches(amatches, (menucur ? (*menucur)->gnum : -1));
+    return 0;
+}
+
+static int
+markcollistmatches(Hookdef dummy, void **m)
+{
+    if (listshown && menucur)
+	icollistmatches(((Cmgroup) m[0]), ((Cmatch) m[1])->gnum);
+    return 0;
+}
+
+static int
+menuselect(char **args)
+{
+    Cmatch **p;
+    Cmgroup *pg;
+    Thingy cmd;
+    int i = 0;
+
+    if (!menucur)
+	menucomplete(args);
+
+    if (!menucur)
+	return 1;
+
+    noselect = 0;
+    mselect = (*menucur)->gnum;
+    for (;;) {
+	showinglist = -2;
+	zrefresh();
+	if (noselect)
+	    break;
+	if (!i) {
+	    i = mcols * mlines;
+	    while (i--)
+		if (mtab[i])
+		    break;
+	    if (!i)
+		break;
+	    i = 1;
+	}
+	p = mtab + mcol + (mline * mcols);
+	pg = mgtab + mcol + (mline * mcols);
+	menucur = *p;
+	menugrp = *pg;
+
+    getk:
+
+	if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak) ||
+	    cmd == Th(z_acceptline))
+	    break;
+	else if (cmd == Th(z_acceptandhold)) {
+	    acceptlast();
+	} else if (cmd == Th(z_redisplay)) {
+	    redisplay(zlenoargs);
+	    continue;
+	} else if (cmd == Th(z_clearscreen)) {
+	    clearscreen(zlenoargs);
+	    continue;
+	} else if (cmd == Th(z_downhistory) ||
+		   cmd == Th(z_downlineorhistory) ||
+		   cmd == Th(z_downlineorsearch) ||
+		   cmd == Th(z_vidownlineorhistory)) {
+	    do {
+		if (mline == mlines - 1) {
+		    p -= mline * mcols;
+		    mline = 0;
+		} else {
+		    mline++;
+		    p += mcols;
+		}
+	    } while (!*p);
+	} else if (cmd == Th(z_uphistory) ||
+		   cmd == Th(z_uplineorhistory) ||
+		   cmd == Th(z_uplineorsearch) ||
+		   cmd == Th(z_viuplineorhistory)) {
+	    do {
+		if (!mline) {
+		    mline = mlines - 1;
+		    p += mline * mcols;
+		} else {
+		    mline--;
+		    p -= mcols;
+		}
+	    } while (!*p);
+	} else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) {
+	    do {
+		if (mcol == mcols - 1) {
+		    p -= mcol;
+		    mcol = 0;
+		} else {
+		    mcol++;
+		    p++;
+		}
+	    } while (!*p);
+	} else if (cmd == Th(z_backwardchar) || cmd == Th(z_vibackwardchar)) {
+	    do {
+		if (!mcol) {
+		    mcol = mcols - 1;
+		    p += mcol;
+		} else {
+		    mcol--;
+		    p--;
+		}
+	    } while (!*p);
+	} else if (cmd == Th(z_beginningofbufferorhistory) ||
+		   cmd == Th(z_beginningofline) ||
+		   cmd == Th(z_beginningoflinehist) ||
+		   cmd == Th(z_vibeginningofline)) {
+	    p -= mcol;
+	    mcol = 0;
+	    while (!*p) {
+		mcol++;
+		p++;
+	    }
+	} else if (cmd == Th(z_endofbufferorhistory) ||
+		   cmd == Th(z_endofline) ||
+		   cmd == Th(z_endoflinehist) ||
+		   cmd == Th(z_viendofline)) {
+	    p += mcols - mcol - 1;
+	    mcol = mcols - 1;
+	    while (!*p) {
+		mcol--;
+		p--;
+	    }
+	} else if (cmd == Th(z_forwardword) ||
+		   cmd == Th(z_emacsforwardword) ||
+		   cmd == Th(z_viforwardword) ||
+		   cmd == Th(z_viforwardwordend)) {
+	    Cmgroup g = *pg;
+	    int ol = mline;
+
+	    do {
+		if (mline == mlines - 1) {
+		    p -= mline * mcols;
+		    pg -= mline * mcols;
+		    mline = 0;
+		} else {
+		    mline++;
+		    p += mcols;
+		    pg += mcols;
+		}
+	    } while (ol != mline && (*pg == g || !*pg));
+	} else if (cmd == Th(z_backwardword) ||
+		   cmd == Th(z_emacsbackwardword) ||
+		   cmd == Th(z_vibackwardword)) {
+	    Cmgroup g = *pg;
+	    int ol = mline;
+
+	    do {
+		if (!mline) {
+		    mline = mlines - 1;
+		    p += mline * mcols;
+		    pg += mline * mcols;
+		} else {
+		    mline--;
+		    p -= mcols;
+		    pg -= mcols;
+		}
+	    } while (ol != mline && (*pg == g || !*pg));
+	} else
+	    goto getk;
+
+	do_single(**p);
+	mselect = (**p)->gnum;
+    }
+    mselect = -1;
     return 0;
 }
 
@@ -543,7 +767,6 @@
 int
 setup_example(Module m)
 {
-    addhookfunc("list_matches", (Hookfn) collistmatches);
     return 0;
 }
 
@@ -551,6 +774,18 @@
 int
 boot_example(Module m)
 {
+    mtab = NULL;
+    mselect = -1;
+
+    w_menuselect = addzlefunction("menu-select", menuselect,
+                                    ZLE_MENUCMP|ZLE_KEEPSUFFIX|ZLE_ISCOMP);
+    if (!w_menuselect) {
+	zwarnnam(m->nam, "name clash when adding ZLE function `menu-select'",
+		 NULL, 0);
+	return -1;
+    }
+    addhookfunc("list_matches", (Hookfn) collistmatches);
+    addhookfunc("insert_match", (Hookfn) markcollistmatches);
     return 0;
 }
 
@@ -560,6 +795,11 @@
 int
 cleanup_example(Module m)
 {
+    free(mtab);
+
+    deletezlefunction(w_menuselect);
+    deletehookfunc("list_matches", (Hookfn) collistmatches);
+    deletehookfunc("insert_match", (Hookfn) markcollistmatches);
     return 0;
 }
 
@@ -567,7 +807,6 @@
 int
 finish_example(Module m)
 {
-    deletehookfunc("list_matches", (Hookfn) collistmatches);
     return 0;
 }
 
diff -u -r oos/Zle/zle_main.c Src/Zle/zle_main.c
--- oos/Zle/zle_main.c	Mon Jun 21 11:07:12 1999
+++ Src/Zle/zle_main.c	Mon Jun 21 11:08:00 1999
@@ -959,6 +959,7 @@
 /**/
 struct hookdef zlehooks[] = {
     HOOKDEF("list_matches", ilistmatches, 0),
+    HOOKDEF("insert_match", NULL, HOOKF_ALL),
 };
 
 /**/
diff -u -r oos/Zle/zle_tricky.c Src/Zle/zle_tricky.c
--- oos/Zle/zle_tricky.c	Mon Jun 21 11:07:12 1999
+++ Src/Zle/zle_tricky.c	Mon Jun 21 11:08:01 1999
@@ -113,8 +113,11 @@
 /* Pointers to the current position in the groups list and in the menu-    *
  * completion array (the one that was put in the command line last).       */
 
-static Cmgroup menugrp;
-static Cmatch *menucur;
+/**/
+Cmgroup menugrp;
+
+/**/
+Cmatch *menucur;
 
 /* menupos is the point (in the command line) where the menu-completion   *
  * strings are inserted.  menulen is the length of the string that was    *
@@ -541,7 +544,8 @@
  * with the next completions. This gives you a way to   *
  * accept several selections from the list of matches.  */
 
-static void
+/**/
+void
 acceptlast(void)
 {
     if (brbeg && *brbeg) {
@@ -7513,7 +7517,7 @@
 /* Insert a single match in the command line. */
 
 /**/
-static void
+void
 do_single(Cmatch m)
 {
     int l, sr = 0, scs;
@@ -7669,6 +7673,17 @@
 
     if ((menucmp && !menuwe) || !movetoend)
 	cs = menuend;
+    {
+	void *data[2];
+	Cmatch *om = menucur;
+
+	if (menucmp)
+	    menucur = &m;
+	data[0] = (void *) amatches;
+	data[1] = (void *) m;
+	runhookdef(zlehooks + 1, (void *) data);
+	menucur = om;
+    }
 }
 
 /* This maps the value in v into the range [0,m-1], decrementing v

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author