zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: groups in ZLS_COLOURS (and questions)
@ 1999-12-02 14:01 Sven Wischnowsky
  0 siblings, 0 replies; 3+ messages in thread
From: Sven Wischnowsky @ 1999-12-02 14:01 UTC (permalink / raw)
  To: zsh-workers


I wrote:

> One last comment about this colouring: I guess with this per-group and 
> pattern matching stuff going on somebody will ask if it wouldn't be
> possible to highlight different line-parts of, say, a process listing
> differently (e.g. pids in red cmd-line in blue or whatever).

Certainly one of the sicker things I've ever written...

This allows pattern specs to define different codes for different
parts of the matched pattern. The pattern has to use `(#b)' and the
codes for the parts are defined by additional `=<values>'
strings. E.g.:

  ZLS_COLOURS='(processes)=(#b)?(?????)???????????????????????????(*)=0=1=4'

gives (me, at least; with the ps(1) I have here) process ids in bold
and underlined command lines. (That first `=0', btw, gives the code to 
use for `the rest'.)

On the C-code side there are only some changes in complist.c, the
private versions of printfmt() and nicezputs() as I already said (but
both are very small), and the function pattryrefs() in pattern.c which 
allows one to easily get at the positions for backreferences.

Dunno if this is considered worth including. But it was fun writing
it, I'm still chuckling...


Bye
 Sven

diff -u -r oldsrc/Zle/complist.c Src/Zle/complist.c
--- oldsrc/Zle/complist.c	Thu Dec  2 11:39:40 1999
+++ Src/Zle/complist.c	Thu Dec  2 14:30:52 1999
@@ -60,6 +60,10 @@
 
 #define NUM_COLS 16
 
+/* Maximum number of in-string colours supported. */
+
+#define MAX_POS 11
+
 /* Names of the terminal strings. */
 
 static char *colnames[] = {
@@ -91,7 +95,7 @@
 struct patcol {
     Patprog prog;
     Patprog pat;		/* pattern for match */
-    char *col;
+    char *cols[MAX_POS + 1];
     Patcol next;
 };
 
@@ -120,11 +124,11 @@
  * The return value is a pointer to the character after it. */
 
 static char *
-getcolval(char *s)
+getcolval(char *s, int multi)
 {
     char *p;
 
-    for (p = s; *s && *s != ':'; p++, s++) {
+    for (p = s; *s && *s != ':' && (!multi || *s != '='); p++, s++) {
 	if (*s == '\\' && s[1]) {
 	    switch (*++s) {
 	    case 'a': *p = '\007'; break;
@@ -212,7 +216,7 @@
 	if (!*s)
 	    return s;
 	*s++ = '\0';
-	p = getcolval(s);
+	p = getcolval(s, 0);
 	ec = (Extcol) zhalloc(sizeof(*ec));
 	ec->prog = gprog;
 	ec->ext = n;
@@ -228,7 +232,8 @@
 	    *p++ = '\0';
 	return p;
     } else if (*s == '=') {
-	char *p = ++s, *t;
+	char *p = ++s, *t, *cols[MAX_POS];
+	int ncols = 0;
 	Patprog prog;
 
 	/* This is for a pattern. */
@@ -238,15 +243,26 @@
 	if (!*s)
 	    return s;
 	*s++ = '\0';
-	t = getcolval(s);
+	while (1) {
+	    t = getcolval(s, 1);
+	    if (ncols < MAX_POS)
+		cols[ncols++] = s;
+	    s = t;
+	    if (*s != '=')
+		break;
+	    *s++ = '\0';
+	}
 	tokenize(p);
 	if ((prog = patcompile(p, 0, NULL))) {
 	    Patcol pc, po;
+	    int i;
 
 	    pc = (Patcol) zhalloc(sizeof(*pc));
 	    pc->prog = gprog;
 	    pc->pat = prog;
-	    pc->col = s;
+	    for (i = 0; i < ncols; i++)
+		pc->cols[i] = cols[i];
+	    pc->cols[i] = NULL;
 	    pc->next = NULL;
 	    if ((po = c->pats)) {
 		while (po->next)
@@ -272,7 +288,7 @@
 	for (i = 0, nn = colnames; *nn; i++, nn++)
 	    if (!strcmp(n, *nn))
 		break;
-	p = getcolval(s);
+	p = getcolval(s, 0);
 	if (*nn) {
 	    Filecol fc, fo;
 
@@ -369,6 +385,14 @@
 static Cmgroup *mgtab, *mgtabp;
 static struct listcols mcolors;
 
+/* Information for in-string colours. */
+
+static int nrefs;
+static int begpos[MAX_POS], curisbeg;
+static int endpos[MAX_POS], curisend;
+static char **patcols, *curiscols[MAX_POS];
+static int curiscol;
+
 /* The last color used. */
 
 static char *last_cap;
@@ -414,28 +438,131 @@
 	zcputs(&mcolors, NULL, COL_NO);
 }
 
-/* Get the terminal color string for the given match. */
 
 static void
+initiscol(Listcols c)
+{
+    int i;
+
+    zlrputs(c, patcols[0]);
+
+    curiscols[curiscol = 0] = *patcols++;
+
+    curisbeg = curisend = 0;
+
+    for (i = nrefs;  i < MAX_POS; i++)
+	begpos[i] = -1, endpos[i] = 0xfffffff;
+}
+
+static void
+doiscol(Listcols c, int pos)
+{
+    if (pos > endpos[curisend]) {
+	curisend++;
+	if (curiscol) {
+	    zcputs(c, NULL, COL_NO);
+	    zlrputs(c, curiscols[--curiscol]);
+	}
+    }
+    if (pos == begpos[curisbeg] && *patcols) {
+	curisbeg++;
+
+	zcputs(c, NULL, COL_NO);
+	zlrputs(c, *patcols);
+
+	curiscols[++curiscol] = *patcols++;
+    }
+}
+
+/* Stripped-down version of printfmt(). But can do in-string colouring. */
+
+static void
+clprintfmt(Listcols c, char *p)
+{
+    int cc = 0, i = 0;
+
+    initiscol(c);
+
+    for (; *p; p++) {
+	doiscol(c, i++);
+	cc++;
+	if (*p == '\n') {
+	    if (tccan(TCCLEAREOL))
+		tcout(TCCLEAREOL);
+	    else {
+		int s = columns - 1 - (cc % columns);
+
+		while (s-- > 0)
+		    putc(' ', shout);
+	    }
+	    cc = 0;
+	}
+	putc(*p, shout);
+    }
+    if (tccan(TCCLEAREOL))
+	tcout(TCCLEAREOL);
+    else {
+	int s = columns - 1 - (cc % columns);
+
+	while (s-- > 0)
+	    putc(' ', shout);
+    }
+}
+
+/* Local version of nicezputs() with in-string colouring. */
+
+static void
+clnicezputs(Listcols c, char *s)
+{
+    int cc, i = 0;
+
+    initiscol(c);
+
+    while ((cc = *s++)) {
+	doiscol(c, i++);
+	if (itok(cc)) {
+	    if (cc <= Comma)
+		cc = ztokens[cc - Pound];
+	    else 
+		continue;
+	}
+	if (cc == Meta)
+	    cc = *s++ ^ 32;
+	fputs(nicechar(cc), shout);
+    }
+}
+
+/* Get the terminal color string for the given match. */
+
+static int
 putmatchcol(Listcols c, char *group, char *n)
 {
     Patcol pc;
 
+    nrefs = MAX_POS - 1;
+
     for (pc = c->pats; pc; pc = pc->next)
 	if ((!pc->prog || !group || pattry(pc->prog, group)) &&
-	    pattry(pc->pat, n)) {
-	    zlrputs(c, pc->col);
+	    pattryrefs(pc->pat, n, &nrefs, begpos, endpos)) {
+	    if (pc->cols[1]) {
+		patcols = pc->cols;
 
-	    return;
+		return 1;
+	    }
+	    zlrputs(c, pc->cols[0]);
+
+	    return 0;
 	}
 
     zcputs(c, group, COL_NO);
+
+    return 0;
 }
 
 /* Get the terminal color string for the file with the given name and
  * file modes. */
 
-static void
+static int
 putfilecol(Listcols c, char *group, char *n, mode_t m)
 {
     int colour;
@@ -447,14 +574,22 @@
 	    (!ec->prog || !group || pattry(ec->prog, group))) {
 	    zlrputs(c, ec->col);
 
-	    return;
+	    return 0;
 	}
+
+    nrefs = MAX_POS - 1;
+
     for (pc = c->pats; pc; pc = pc->next)
 	if ((!pc->prog || !group || pattry(pc->prog, group)) &&
-	    pattry(pc->pat, n)) {
-	    zlrputs(c, pc->col);
+	    pattryrefs(pc->pat, n, &nrefs, begpos, endpos)) {
+	    if (pc->cols[1]) {
+		patcols = pc->cols;
 
-	    return;
+		return 1;
+	    }
+	    zlrputs(c, pc->cols[0]);
+
+	    return 0;
 	}
 
     if (S_ISDIR(m))
@@ -475,6 +610,8 @@
 	colour = COL_FI;
 
     zcputs(c, group, colour);
+
+    return 0;
 }
 
 static void
@@ -482,7 +619,7 @@
 	 char *path, struct stat *buf)
 {
     Cmatch m;
-    int len;
+    int len, subcols = 0;
 
     if (!mp) {
 	zcputs(&mcolors, g->name, COL_MI);
@@ -511,8 +648,11 @@
 	    mmlen = mcols;
 	    zcputs(&mcolors, g->name, COL_MA);
 	} else
-	    putmatchcol(&mcolors, g->name, m->disp);
-	printfmt(m->disp, 0, 1, 0);
+	    subcols = putmatchcol(&mcolors, g->name, m->disp);
+	if (subcols)
+	    clprintfmt(&mcolors, m->disp);
+	else
+	    printfmt(m->disp, 0, 1, 0);
 	zcoff();
     } else {
 	int mx;
@@ -543,11 +683,14 @@
 	    mmlen = width;
 	    zcputs(&mcolors, g->name, COL_MA);
 	} else if (buf)
-	    putfilecol(&mcolors, g->name, path, buf->st_mode);
+	    subcols = putfilecol(&mcolors, g->name, path, buf->st_mode);
 	else
-	    putmatchcol(&mcolors, g->name, (m->disp ? m->disp : m->str));
+	    subcols = putmatchcol(&mcolors, g->name, (m->disp ? m->disp : m->str));
 
-	nicezputs((m->disp ? m->disp : m->str), shout);
+	if (subcols)
+	    clnicezputs(&mcolors, (m->disp ? m->disp : m->str));
+	else
+	    nicezputs((m->disp ? m->disp : m->str), shout);
 	len = niceztrlen(m->disp ? m->disp : m->str);
 
 	 if (isset(LISTTYPES) && buf) {
diff -u -r oldsrc/pattern.c Src/pattern.c
--- oldsrc/pattern.c	Thu Dec  2 11:39:37 1999
+++ Src/pattern.c	Thu Dec  2 14:16:49 1999
@@ -1283,10 +1283,25 @@
 mod_export int
 pattry(Patprog prog, char *string)
 {
-    int i;
+    return pattryrefs(prog, string, NULL, NULL, NULL);
+}
+
+/* The last three arguments are used to report the positions for the
+ * backreferences. On entry, *nump should contain the maximum number
+ * positions to report. */
+
+/**/
+mod_export int
+pattryrefs(Patprog prog, char *string, int *nump, int *begp, int *endp)
+{
+    int i, maxnpos;
     char **sp, **ep;
     char *progstr = (char *)prog + prog->startoff;
 
+    if (nump) {
+	maxnpos = *nump;
+	*nump = 0;
+    }
     /* inherited from domatch, but why, exactly? */
     if (*string == Nularg)
 	string++;
@@ -1350,7 +1365,28 @@
 		setiparam("MEND",
 			  (zlong)(mlen + patoffset + !isset(KSHARRAYS) - 1));
 	    }
-	    if (prog->patnpar && !(patflags & PAT_FILE)) {
+	    if (prog->patnpar && nump) {
+		/*
+		 * b flag: for backreferences using parentheses. Reported
+		 * directly.
+		 */
+		*nump = prog->patnpar;
+
+		sp = patbeginp;
+		ep = patendp;
+
+		for (i = 0; i < prog->patnpar && i < maxnpos; i++) {
+		    DPUTS(!*sp || !*ep, "BUG: backrefs not set.");
+
+		    if (begp)
+			*begp++ = ztrsub(*sp, patinstart) + patoffset;
+		    if (endp)
+			*endp++ = ztrsub(*ep, patinstart) + patoffset - 1;
+
+		    sp++;
+		    ep++;
+		}
+	    } else if (prog->patnpar && !(patflags & PAT_FILE)) {
 		/*
 		 * b flag: for backreferences using parentheses.
 		 */
diff -u olddoc/Zsh/mod_complist.yo Doc/Zsh/mod_complist.yo
--- olddoc/Zsh/mod_complist.yo	Thu Dec  2 11:39:46 1999
+++ Doc/Zsh/mod_complist.yo	Thu Dec  2 14:49:42 1999
@@ -78,10 +78,23 @@
 string will be used for all files whose name ends with the string.
 The var(name) may also be a equal sign (`tt(=)') followed by a
 pattern. The var(value) given for this pattern will be used for all
-matches (not only filenames) that whose display string are matched by
+matches (not only filenames) whose display string are matched by
 the pattern. Definitions for both of these take precedence over the
 values defined for file types and the form with the leading asterisk 
 takes precedence over the form with the leading equal sign.
+
+The last form also allows to color separate parts of the displayed
+strings using different colors. For this, the pattern has to use the
+`tt((#b))' globbing flag and pairs of parentheses surrounding the
+parts of the strings that are to be colored differently. In this case 
+the var(value) may consist of more than one color code separated by
+equal signs. The first code will be used for all parts for which no
+explicit code is specified and the following codes will be used for
+the parts matched by the sub-patterns in parentheses. For example,
+the specification `tt(=(#b)(?)*(?)=0=3=7)' will be used for all
+matches which are at least two characters long and will make the use
+the code `tt(3)' for the first character, `tt(7)' for the last
+character and `tt(0)' for the rest.
 
 All three forms of var(name) may be preceded by a pattern in
 parentheses. If such a pattern is given, the var(value) will be used

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: PATCH: groups in ZLS_COLOURS (and questions)
@ 1999-12-03  8:54 Sven Wischnowsky
  0 siblings, 0 replies; 3+ messages in thread
From: Sven Wischnowsky @ 1999-12-03  8:54 UTC (permalink / raw)
  To: zsh-workers


I wrote:

> What this patch doesn't do is make this configurable with styles.
> That's because I'm not sure how to do that best. What I would like to
> achieve is that one could do, e.g.:
> 
>   compstyle '*:jobs' list-colors <specs...>
> 
> which would make the completion code use these patterns only for
> groups named `jobs'. Building appropriate specs for ZLS_* is
> simple. But there are three problems I see:

This patch does that (and the list-colors style for the default tag to 
get specs that are to be used everywhere).

NOTE: this means that the completion system has to change the
ZLS_COLORS parameter. So, if you have that set, it won't work for you
any more -- I couldn't think of a way to use the value stored in oe of 
the ZLS_* params as the defaults. Sorry. But you can easily convert
your definition to styles, just add:

  compstyle '*:default' list-colors ${(s.:.)ZLS_COLORS}

to your other compstyle stuff.


Or did anyone have a better idea?


Internals: this adds the function _setup to look up and styles and set 
ZLS_COLORS. This function will get somewhat bigger when we make more
things configurable with styles.

This also fixes a small typo/thinko in computil.c -- compstyles
couldn't be called without strings for the value.

Bye
 Sven

diff -u -r oldcompletion/Core/_description Completion/Core/_description
--- oldcompletion/Core/_description	Thu Dec  2 15:02:30 1999
+++ Completion/Core/_description	Fri Dec  3 09:23:29 1999
@@ -14,6 +14,8 @@
 
 _lastdescr=( "$_lastdescr[@]" "$3" )
 
+_setup "$1"
+
 _style -s descriptions format format
 _style -s "$1" group-name gname && [[ -z "$gname" ]] && gname="$1"
 
diff -u -r oldcompletion/Core/_files Completion/Core/_files
--- oldcompletion/Core/_files	Thu Dec  2 15:02:30 1999
+++ Completion/Core/_files	Fri Dec  3 09:23:29 1999
@@ -27,19 +27,31 @@
 
 while _tags; do
   if _requested all-files; then
-    (( $#group )) && group[2]=all-files
+    if (( $#group )); then
+      group[2]=all-files
+      _setup all-files
+    fi
     _path_files "$opts[@]" -f
     return
   elif _requested directories; then
     if _requested globbed-files; then
-      (( $#group )) && group[2]=globbed-files
+      if (( $#group )); then
+        group[2]=globbed-files
+	_setup globbed-files
+      fi
       _path_files "$opts[@]" -/g "$type" && return 0
     else
-      (( $#group )) && group[2]=directories
+      if (( $#group )); then
+        group[2]=directories
+	_setup directories
+      fi
       _path_files "$opts[@]" -/ && return 0
     fi
   elif _requested globbed-files; then
-    (( $#group )) && group[2]=globbed-files
+    if (( $#group )); then
+      group[2]=globbed-files
+      _setup globbed-files
+    fi
     _path_files "$opts[@]" -g "$type" && return 0
   fi
 done
diff -u -r oldcompletion/Core/_main_complete Completion/Core/_main_complete
--- oldcompletion/Core/_main_complete	Thu Dec  2 15:02:30 1999
+++ Completion/Core/_main_complete	Fri Dec  3 09:31:09 1999
@@ -39,6 +39,10 @@
   compstate[context]=tilde
 fi
 
+# Initial setup.
+
+_setup default
+
 # Get the names of the completers to use in the positional parameters.
 
 if (( ! $# )); then
diff -u -r oldcompletion/Core/compinit Completion/Core/compinit
--- oldcompletion/Core/compinit	Thu Dec  2 15:02:31 1999
+++ Completion/Core/compinit	Fri Dec  3 09:33:36 1999
@@ -487,12 +487,13 @@
 
 # Default styles. This should be executed conditionally somehow.
 
-compstyle '*'        verbose       'yes'
-compstyle '*'        prefix-needed 'yes'
-compstyle '*'        prefix-hidden 'no'
-compstyle ':correct' accept        '2n'
-compstyle ':correct' prompt        'correct to:'
-compstyle '*'        completer     '_complete'
+compstyle '*'         verbose       'yes'
+compstyle '*'         prefix-needed 'yes'
+compstyle '*'         prefix-hidden 'no'
+compstyle ':correct'  accept        '2n'
+compstyle ':correct'  prompt        'correct to:'
+compstyle '*'         completer     '_complete'
+compstyle '*:default' list-colors   no=0 fi=0 di=0 ln=0 pi=0 so=0 bd=0 cd=0 ex=0
 
 # Now we automatically make the definition files autoloaded.
 
diff -u olddoc/Zsh/compsys.yo Doc/Zsh/compsys.yo
--- olddoc/Zsh/compsys.yo	Thu Dec  2 15:02:09 1999
+++ Doc/Zsh/compsys.yo	Fri Dec  3 09:43:35 1999
@@ -964,6 +964,27 @@
 Like the tt(arguments) style, but used when calling the tt(ps) command 
 to generate the list to display.
 )
+item(tt(list-colors))(
+If the tt(complist) module is used, this style can be used to set
+color specifications as with the tt(ZLS_COLORS) and tt(ZLS_COLOURS)
+parameters (see
+ifzman(the section `The complist Module' in zmanref(zshmodules))\
+ifnzman(noderef(The complist Module))\
+).
+
+If this style is set for the tt(default) tag, the strings in the value 
+are taken as specifications that are to be used everywhere. If it is
+set for other tags, the specifications are used only for matches of
+the type described by the tag.
+
+To be able to share the same specifications one has set up for the GNU
+version of the tt(ls) command one can use:
+
+example(compstyle '*:default' list-colors ${(s.:.)LS_COLORS})
+
+And to get the default colors (which are the same as for the GNU
+tt(ls) command) one should set the style to an empty value.
+)
 item(tt(local))(
 This style is used by completion functions which generate URLs as
 possible matches to add suitable matches when a URL points to a
diff -u olddoc/Zsh/compwid.yo Doc/Zsh/compwid.yo
--- olddoc/Zsh/compwid.yo	Thu Dec  2 15:02:09 1999
+++ Doc/Zsh/compwid.yo	Fri Dec  3 09:23:31 1999
@@ -372,7 +372,7 @@
 startitem()
 findex(compadd)
 cindex(completion widgets, adding specified matches)
-xitem(tt(compadd) [ tt(-qQfenUaml12) ] [ tt(-F) var(array) ])
+xitem(tt(compadd) [ tt(-qQfenUal12) ] [ tt(-F) var(array) ])
 xitem([ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
 xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
 xitem([ tt(-i) var(ignored-prefix) ] [ tt(-I) var(ignored-suffix) ])
@@ -449,7 +449,7 @@
 )
 item(tt(-l))(
 This option only has an effect if used together with the tt(-d)
-options. If it is given, the display strings are listed one per line,
+option. If it is given, the display strings are listed one per line,
 not arrayed in columns.
 )
 item(tt(-J) var(name))(
diff -u olddoc/Zsh/mod_complist.yo Doc/Zsh/mod_complist.yo
--- olddoc/Zsh/mod_complist.yo	Thu Dec  2 15:02:11 1999
+++ Doc/Zsh/mod_complist.yo	Fri Dec  3 09:23:31 1999
@@ -118,6 +118,13 @@
 vt100 compatible terminals such as tt(xterm)s. On monochrome terminals
 the default values will have no visual effect.
 
+If the shell function based completion system is used, these
+parameters should not be set directly because the system controls them 
+itself. Instead, the tt(list-colors) style should be used (see
+ifzman(the section `Completion System Configuration' in zmanref(zshcompsys))\
+ifnzman(noderef(Completion System Configuration))\
+).
+
 subsect(Menu selection)
 cindex(completion, selecting by cursor)
 vindex(SELECTMIN)
diff -u oldsrc/Zle/computil.c Src/Zle/computil.c
--- oldsrc/Zle/computil.c	Thu Dec  2 15:02:05 1999
+++ Src/Zle/computil.c	Fri Dec  3 09:43:21 1999
@@ -2436,7 +2436,7 @@
 	return 1;
     }
     switch (args[0][1]) {
-    case 'a': min = 3; max = -1; break;
+    case 'a': min = 2; max = -1; break;
     case 'd': min = 0; max =  2; break;
     case 'S': min = 3; max =  3; break;
     case 'A': min = 3; max =  3; break;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* PATCH: groups in ZLS_COLOURS (and questions)
@ 1999-12-02 10:39 Sven Wischnowsky
  0 siblings, 0 replies; 3+ messages in thread
From: Sven Wischnowsky @ 1999-12-02 10:39 UTC (permalink / raw)
  To: zsh-workers


Step by step...


This allows to make specs in ZLS_COLO(|U)RS work only in certain
groups. For now I've taken the syntax `(group-pat)<spec>', i.e. a pattern 
for the group name(s) has to be given at the beginning in parentheses.

Another enhancement is that one can also give pattern-specs that will
be used for all matches (not only files, but also files). The syntax
for that is now `=<pat>=<color-code>'.

Of course, the syntax for both of them can easily be changed if you
don't like it.


What this patch doesn't do is make this configurable with styles.
That's because I'm not sure how to do that best. What I would like to
achieve is that one could do, e.g.:

  compstyle '*:jobs' list-colors <specs...>

which would make the completion code use these patterns only for
groups named `jobs'. Building appropriate specs for ZLS_* is
simple. But there are three problems I see:

1) Where to do it. I think I would put this in a helper function that
can would be called from _description (and from _files because that
has to mess around with the group names).

2) How to merge different definitions. Most of the things we could do
before affected only file names but there were already some specs that 
have to take affect everywhere (the lc, rc, ec capabilities, for
example). With the per-group specs above the user would either have to
include the definitions for these things (and other specs he wants to
have used everywhere) in every value for list-colors or we make the
completion code look up such default specs at some central place
(e.g. _main_complete) and the special specs are then appended to that
when then groups are added. The problem is that I don't know if that
nice enough, maybe if we use a tag `default' (or `global'?) for that:

  compstyle '*:default' list-colors lc=... rc=...
  compstyle '*:jobs' list-colors ...

Would that be ok? Btw, when we do this with styles we could also use
more descriptive names for the capabilities and a nicer syntax for the 
extension (`*.foo=<color>') and pattern (`=<pat>=<color>') specs. I
would then probably try to get some help from computil for this.

3) When and how to set ZLS_*. The completion system would have to
set/change the value of one of these. But what if a user has set it
already? Is it enough to document that one shouldn't set it directly
when using the new completion system? And document that one can use:

  compstyle '*(files|directories)' list-colors ${(s.:.)LS_COLORS}

(or put it into the `default' list-colors style) to include the stuff
one uses for GNU ls?

The same question is important when we try to support things like
menu-selection via styles, btw, so I'd really like to hear your
opinions and suggestions here.


One last comment about this colouring: I guess with this per-group and 
pattern matching stuff going on somebody will ask if it wouldn't be
possible to highlight different line-parts of, say, a process listing
differently (e.g. pids in red cmd-line in blue or whatever).
This is something even I may like so I'm thinking about it. One step
would be to enhance the pattern matching code to directly report
backreferences in integer arrays (so that we don't have to set/use the 
match arrays). Doesn't look to hairy. Being able to print different
parts of a string in different colours is more difficult. complist
would have to implement its own versions of printfmt() and
nicezputs(). Hm. But still, looks like something I could like to play
with...


Bye
 Sven

diff -u oldsrc/Zle/compcore.c Src/Zle/compcore.c
--- oldsrc/Zle/compcore.c	Thu Dec  2 10:16:19 1999
+++ Src/Zle/compcore.c	Thu Dec  2 09:30:23 1999
@@ -445,9 +445,8 @@
     /* We may have to reset the cursor to its position after the   *
      * string inserted by the last completion. */
 
-    if (fromcomp & FC_INWORD)
-	if ((cs = lastend) > ll)
-	    cs = ll;
+    if ((fromcomp & FC_INWORD) && (cs = lastend) > ll)
+	cs = ll;
 
     /* Check if we have to start a menu-completion (via automenu). */
 
@@ -2512,6 +2511,7 @@
 	n->mcount = g->mcount;
 	n->matches = p = (Cmatch *) ncalloc((n->mcount + 1) *
 					    sizeof(Cmatch));
+	n->name = ztrdup(g->name);
 	for (q = g->matches; *q; q++, p++)
 	    *p = dupmatch(*q, nbrbeg, nbrend);
 	*p = NULL;
@@ -2609,6 +2609,7 @@
 	    }
 	    free(g->expls);
 	}
+	zsfree(g->name);
 	free(g);
 
 	g = n;
diff -u oldsrc/Zle/complist.c Src/Zle/complist.c
--- oldsrc/Zle/complist.c	Thu Dec  2 10:16:19 1999
+++ Src/Zle/complist.c	Thu Dec  2 11:05:27 1999
@@ -74,11 +74,33 @@
     "\033[", "m", NULL, "0", "0", "7"
 };
 
+/* This describes a terminal string for a file type. */
+
+typedef struct filecol *Filecol;
+
+struct filecol {
+    Patprog prog;		/* group pattern */
+    char *col;			/* color string */
+    Filecol next;		/* next one */
+};
+
+/* This describes a terminal string for a pattern. */
+
+typedef struct patcol *Patcol;
+
+struct patcol {
+    Patprog prog;
+    Patprog pat;		/* pattern for match */
+    char *col;
+    Patcol next;
+};
+
 /* This describes a terminal string for a filename extension. */
 
 typedef struct extcol *Extcol;
 
 struct extcol {
+    Patprog prog;		/* group pattern or NULL */
     char *ext;			/* the extension */
     char *col;			/* the terminal color string */
     Extcol next;		/* the next one in the list */
@@ -89,7 +111,8 @@
 typedef struct listcols *Listcols;
 
 struct listcols {
-    char *cols[NUM_COLS];	/* strings for file types */
+    Filecol files[NUM_COLS];	/* strings for file types */
+    Patcol pats;		/* strings for patterns */
     Extcol exts;		/* strings for extensions */
 };
 
@@ -152,8 +175,33 @@
 static char *
 getcoldef(Listcols c, char *s)
 {
+    Patprog gprog = NULL;
+
+    if (*s == '(') {
+	char *p;
+	int l = 0;
+
+	for (p = s + 1, l = 0; *p && (*p != ')' || l); p++)
+	    if (*p == '\\' && p[1])
+		p++;
+	    else if (*p == '(')
+		l++;
+	    else if (*p == ')')
+		l--;
+
+	if (*p == ')') {
+	    char sav = p[1];
+
+	    p[1] = '\0';
+	    tokenize(s);
+	    gprog = patcompile(s, 0, NULL);
+	    p[1]  =sav;
+
+	    s = p + 1;
+	}
+    }
     if (*s == '*') {
-	Extcol ec;
+	Extcol ec, eo;
 	char *n, *p;
 
 	/* This is for an extension. */
@@ -166,13 +214,50 @@
 	*s++ = '\0';
 	p = getcolval(s);
 	ec = (Extcol) zhalloc(sizeof(*ec));
+	ec->prog = gprog;
 	ec->ext = n;
 	ec->col = s;
-	ec->next = c->exts;
-	c->exts = ec;
+	ec->next = NULL;
+	if ((eo = c->exts)) {
+	    while (eo->next)
+		eo = eo->next;
+	    eo->next = ec;
+	} else
+	    c->exts = ec;
 	if (*p)
 	    *p++ = '\0';
 	return p;
+    } else if (*s == '=') {
+	char *p = ++s, *t;
+	Patprog prog;
+
+	/* This is for a pattern. */
+
+	while (*s && *s != '=')
+	    s++;
+	if (!*s)
+	    return s;
+	*s++ = '\0';
+	t = getcolval(s);
+	tokenize(p);
+	if ((prog = patcompile(p, 0, NULL))) {
+	    Patcol pc, po;
+
+	    pc = (Patcol) zhalloc(sizeof(*pc));
+	    pc->prog = gprog;
+	    pc->pat = prog;
+	    pc->col = s;
+	    pc->next = NULL;
+	    if ((po = c->pats)) {
+		while (po->next)
+		    po = po->next;
+		po->next = pc;
+	    } else
+		c->pats = pc;
+	}
+	if (*t)
+	    *t++ = '\0';
+	return t;
     } else {
 	char *n = s, *p, **nn;
 	int i;
@@ -185,17 +270,43 @@
 	    return s;
 	*s++ = '\0';
 	for (i = 0, nn = colnames; *nn; i++, nn++)
-	    if (!strcmp(n ,*nn))
+	    if (!strcmp(n, *nn))
 		break;
 	p = getcolval(s);
-	if (*nn)
-	    c->cols[i] = s;
+	if (*nn) {
+	    Filecol fc, fo;
+
+	    fc = (Filecol) zhalloc(sizeof(*fc));
+	    fc->prog = (i == COL_EC || i == COL_LC || i == COL_RC ?
+			NULL : gprog);
+	    fc->col = s;
+	    fc->next = NULL;
+	    if ((fo = c->files[i])) {
+		while (fo->next)
+		    fo = fo->next;
+		fo->next = fc;
+	    } else
+		c->files[i] = fc;
+	}
 	if (*p)
 	    *p++ = '\0';
 	return p;
     }
 }
 
+static Filecol
+filecol(char *col)
+{
+    Filecol fc;
+
+    fc = (Filecol) zhalloc(sizeof(*fc));
+    fc->prog = NULL;
+    fc->col = col;
+    fc->next = NULL;
+
+    return fc;
+}
+
 /* Combined length of LC and RC, maximum length of capability strings. */
 
 static int lr_caplen, max_caplen;
@@ -211,17 +322,18 @@
     if (!(s = getsparam("ZLS_COLORS")) &&
 	!(s = getsparam("ZLS_COLOURS"))) {
 	for (i = 0; i < NUM_COLS; i++)
-	    c->cols[i] = "";
+	    c->files[i] = filecol("");
+	c->pats = NULL;
 	c->exts = NULL;
 	
-	if (!(c->cols[COL_MA] = tcstr[TCSTANDOUTBEG]) ||
-	    !c->cols[COL_MA][0])
-	    c->cols[COL_MA] = "";
-	else
-	    c->cols[COL_EC] = tcstr[TCSTANDOUTEND];
+	if ((s = tcstr[TCSTANDOUTBEG]) && s[0]) {
+	    c->files[COL_MA] = filecol(s);
+	    c->files[COL_EC] = filecol(tcstr[TCSTANDOUTEND]);
+	} else
+	    c->files[COL_MA] = filecol("");
 	lr_caplen = 0;
-	if ((max_caplen = strlen(c->cols[COL_MA])) <
-	    (l = strlen(c->cols[COL_EC])))
+	if ((max_caplen = strlen(c->files[COL_MA]->col)) <
+	    (l = strlen(c->files[COL_EC]->col)))
 	    max_caplen = l;
 	return;
     }
@@ -234,16 +346,17 @@
     /* Use default values for those that aren't set explicitly. */
     max_caplen = lr_caplen = 0;
     for (i = 0; i < NUM_COLS; i++) {
-	if (!c->cols[i])
-	    c->cols[i] = defcols[i];
-	if (c->cols[i] && (l = strlen(c->cols[i])) > max_caplen)
+	if (!c->files[i] || !c->files[i]->col)
+	    c->files[i] = filecol(defcols[i]);
+	if (c->files[i] && c->files[i]->col &&
+	    (l = strlen(c->files[i]->col)) > max_caplen)
 	    max_caplen = l;
     }
-    lr_caplen = strlen(c->cols[COL_LC]) + strlen(c->cols[COL_RC]);
+    lr_caplen = strlen(c->files[COL_LC]->col) + strlen(c->files[COL_RC]->col);
 
     /* Default for missing files. */
-    if (!c->cols[COL_MI])
-	c->cols[COL_MI] = c->cols[COL_FI];
+    if (!c->files[COL_MI] || !c->files[COL_MI]->col)
+	c->files[COL_MI] = c->files[COL_FI];
 
     return;
 }
@@ -258,30 +371,36 @@
 
 /* The last color used. */
 
-static int last_col = COL_NO;
+static char *last_cap;
 
 static void
 zlrputs(Listcols c, char *cap)
 {
-    VARARR(char, buf, lr_caplen + max_caplen + 1);
+    if (strcmp(last_cap, cap)) {
+	VARARR(char, buf, lr_caplen + max_caplen + 1);
 
-    strcpy(buf, c->cols[COL_LC]);
-    strcat(buf, cap);
-    strcat(buf, c->cols[COL_RC]);
+	strcpy(buf, c->files[COL_LC]->col);
+	strcat(buf, cap);
+	strcat(buf, c->files[COL_RC]->col);
 
-    tputs(buf, 1, putshout);
+	tputs(buf, 1, putshout);
+
+	strcpy(last_cap, cap);
+    }
 }
 
 static void
-zcputs(Listcols c, int colour)
+zcputs(Listcols c, char *group, int colour)
 {
-    if (colour != last_col
-	&& (last_col < COL_NO
-	    || strcmp(c->cols[last_col], c->cols[colour]))) {
-	zlrputs(c, c->cols[colour]);
-	last_col = colour;
-    }
-    return;
+    Filecol fc;
+
+    for (fc = c->files[colour]; fc; fc = fc->next)
+	if (fc->col &&
+	    (!fc->prog || !group || pattry(fc->prog, group))) {
+	    zlrputs(c, fc->col);
+
+	    return;
+	}
 }
 
 /* Turn off colouring. */
@@ -289,28 +408,52 @@
 static void
 zcoff(void)
 {
-    if (mcolors.cols[COL_EC])
-	tputs(mcolors.cols[COL_EC], 1, putshout);
+    if (mcolors.files[COL_EC] && mcolors.files[COL_EC]->col)
+	tputs(mcolors.files[COL_EC]->col, 1, putshout);
     else
-	zcputs(&mcolors, COL_NO);
+	zcputs(&mcolors, NULL, COL_NO);
+}
+
+/* Get the terminal color string for the given match. */
+
+static void
+putmatchcol(Listcols c, char *group, char *n)
+{
+    Patcol pc;
+
+    for (pc = c->pats; pc; pc = pc->next)
+	if ((!pc->prog || !group || pattry(pc->prog, group)) &&
+	    pattry(pc->pat, n)) {
+	    zlrputs(c, pc->col);
+
+	    return;
+	}
+
+    zcputs(c, group, COL_NO);
 }
 
 /* Get the terminal color string for the file with the given name and
  * file modes. */
 
 static void
-putcolstr(Listcols c, char *n, mode_t m)
+putfilecol(Listcols c, char *group, char *n, mode_t m)
 {
     int colour;
-    Extcol e;
+    Extcol ec;
+    Patcol pc;
+
+    for (ec = c->exts; ec; ec = ec->next)
+	if (strsfx(ec->ext, n) &&
+	    (!ec->prog || !group || pattry(ec->prog, group))) {
+	    zlrputs(c, ec->col);
 
-    for (e = c->exts; e; e = e->next)
-	if (strsfx(e->ext, n)) {	/* XXX: unoptimised if used */
-	    if (last_col < COL_NO
-		|| strcmp(c->cols[last_col], e->col))
-		zlrputs(c, e->col);
+	    return;
+	}
+    for (pc = c->pats; pc; pc = pc->next)
+	if ((!pc->prog || !group || pattry(pc->prog, group)) &&
+	    pattry(pc->pat, n)) {
+	    zlrputs(c, pc->col);
 
-	    last_col = COL_NO - 1;
 	    return;
 	}
 
@@ -331,8 +474,7 @@
     else
 	colour = COL_FI;
 
-    zcputs(c, colour);
-    return;
+    zcputs(c, group, colour);
 }
 
 static void
@@ -340,10 +482,10 @@
 	 char *path, struct stat *buf)
 {
     Cmatch m;
-    int len, cc;
+    int len;
 
     if (!mp) {
-	zcputs(&mcolors, COL_MI);
+	zcputs(&mcolors, g->name, COL_MI);
 	len = width - 2;
 	while (len-- > 0)
 	    putc(' ', shout);
@@ -367,10 +509,9 @@
 	    mmtabp = mtab + mm;
 	    mgtabp = mgtab + mm;
 	    mmlen = mcols;
-	    cc = COL_MA;
+	    zcputs(&mcolors, g->name, COL_MA);
 	} else
-	    cc = COL_NO;
-	zcputs(&mcolors, cc);
+	    putmatchcol(&mcolors, g->name, m->disp);
 	printfmt(m->disp, 0, 1, 0);
 	zcoff();
     } else {
@@ -400,11 +541,11 @@
 	    mmtabp = mtab + mx + mm;
 	    mgtabp = mgtab + mx + mm;
 	    mmlen = width;
-	    zcputs(&mcolors, COL_MA);
+	    zcputs(&mcolors, g->name, COL_MA);
 	} else if (buf)
-	    putcolstr(&mcolors, path, buf->st_mode);
+	    putfilecol(&mcolors, g->name, path, buf->st_mode);
 	else
-	    zcputs(&mcolors, COL_NO);
+	    putmatchcol(&mcolors, g->name, (m->disp ? m->disp : m->str));
 
 	nicezputs((m->disp ? m->disp : m->str), shout);
 	len = niceztrlen(m->disp ? m->disp : m->str);
@@ -412,7 +553,7 @@
 	 if (isset(LISTTYPES) && buf) {
 	    if (m->gnum != mselect) {
 		zcoff();
-		zcputs(&mcolors, COL_TC);
+		zcputs(&mcolors, g->name, COL_TC);
 	    }
 	    putc(file_type(buf->st_mode), shout);
 	    len++;
@@ -420,14 +561,14 @@
 	if ((len = width - len - 2) > 0) {
 	    if (m->gnum != mselect) {
 		zcoff();
-		zcputs(&mcolors, COL_SP);
+		zcputs(&mcolors, g->name, COL_SP);
 	    }
 	    while (len-- > 0)
 		putc(' ', shout);
 	}
 	zcoff();
 	if (!lastc) {
-	    zcputs(&mcolors, COL_NO);
+	    zcputs(&mcolors, g->name, COL_NO);
 	    fputs("  ", shout);
 	    zcoff();
 	}
@@ -483,7 +624,8 @@
 	mcols = columns;
 	mlines = listdat.nlines;
     }
-    last_col = COL_NO - 1;
+    last_cap = (char *) zhalloc(max_caplen + 1);
+    *last_cap = '\0';
 
     if (!printlist(1, clprintm) || listdat.nlines >= lines)
 	noselect = 1;
diff -u olddoc/Zsh/mod_complist.yo Doc/Zsh/mod_complist.yo
--- olddoc/Zsh/mod_complist.yo	Wed Dec  1 16:02:57 1999
+++ Doc/Zsh/mod_complist.yo	Thu Dec  2 09:48:43 1999
@@ -76,6 +76,24 @@
 Apart from these strings, the var(name) may also be an asterisk
 (`tt(*)') followed by any string. The var(value) given for such a
 string will be used for all files whose name ends with the string.
+The var(name) may also be a equal sign (`tt(=)') followed by a
+pattern. The var(value) given for this pattern will be used for all
+matches (not only filenames) that whose display string are matched by
+the pattern. Definitions for both of these take precedence over the
+values defined for file types and the form with the leading asterisk 
+takes precedence over the form with the leading equal sign.
+
+All three forms of var(name) may be preceded by a pattern in
+parentheses. If such a pattern is given, the var(value) will be used
+only for matches in groups whose names are matched by the pattern
+given in the parentheses. E.g. `tt((g*)~m*=43)' says to highlight all
+matches beginning with `tt(m)' in groups whose names  begin with
+`tt(g)' using the color code `tt(43)'. In case of the `tt(lc)',
+`tt(rc)', and `tt(ec)' codes, the group pattern is ignored.
+
+Note also that all patterns are tried in the order in which they
+appear in the parameter value until the first one matches which is
+then used.
 
 When printing a match, the code prints the value of tt(lc), the value
 for the file-type or the last matching specification with a `tt(*)',

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~1999-12-03  8:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-12-02 14:01 PATCH: groups in ZLS_COLOURS (and questions) Sven Wischnowsky
  -- strict thread matches above, loose matches on Subject: below --
1999-12-03  8:54 Sven Wischnowsky
1999-12-02 10:39 Sven Wischnowsky

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).