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

Re: Bug#479576: incorrect interpretation of LS_COLORS link=target by compsys



On Tue, 6 May 2008 15:58:55 +0100
Clint Adams <schizo@xxxxxxxxxx> wrote:
> On Mon, May 05, 2008 at 03:50:16PM +0100, martin f krafft wrote:
> > zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
> > 
> > This is a common way to get colouring of menus and lists by compsys.
> > Unfortunately, it's not aware of all of the features of LS_COLORS.
> > Specifically, if LS_COLORS sets ln=target, that's supposed to mean
> > that the link should be dereferenced and coloured according to the
> > target. zsh unfortunately somehow prepends 'argetm' to the items in
> > the menu list:
> > 
> > lapse:/tmp/cdt.EaF16274% touch a
> > lapse:/tmp/cdt.EaF16274% ln -s a b
> > lapse:/tmp/cdt.EaF16274% ls<tab>
> > a   argetmb@
> 
> Anyone up for special-casing "target" in complist?

It's easier than most things in complist.c and I can't imagine anyone else
is going to looking in the file if they can get away with it.  Fairly
lightly tested (I tried it once and it looked OK).

I've added the traditional bad-tempered comment.

Index: Doc/Zsh/mod_complist.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_complist.yo,v
retrieving revision 1.19
diff -u -r1.19 mod_complist.yo
--- Doc/Zsh/mod_complist.yo	20 Apr 2008 06:41:23 -0000	1.19
+++ Doc/Zsh/mod_complist.yo	6 May 2008 15:49:15 -0000
@@ -37,7 +37,9 @@
 for directories
 )
 item(tt(ln 36))(
-for symbolic links
+for symbolic links.  If this has the special value tt(target),
+symbolic links are dereferenced and the target file used to
+determine the display format.
 )
 item(tt(pi 31))(
 for named pipes (FIFOs)
Index: Src/Zle/comp.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/comp.h,v
retrieving revision 1.16
diff -u -r1.16 comp.h
--- Src/Zle/comp.h	7 Oct 2006 08:05:03 -0000	1.16
+++ Src/Zle/comp.h	6 May 2008 15:49:15 -0000
@@ -114,6 +114,8 @@
     int gnum;			/* global number */
     mode_t mode;                /* mode field of a stat */
     char modec;                 /* LIST_TYPE-character for mode or nul */
+    mode_t fmode;               /* mode field of a stat, following symlink */
+    char fmodec;                /* LIST_TYPE-character for fmode or nul */
 };
 
 #define CMF_FILE     (1<< 0)	/* this is a file */
Index: Src/Zle/compcore.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v
retrieving revision 1.93
diff -u -r1.93 compcore.c
--- Src/Zle/compcore.c	13 Apr 2008 16:58:42 -0000	1.93
+++ Src/Zle/compcore.c	6 May 2008 15:49:16 -0000
@@ -2784,8 +2784,8 @@
 		 (complist ?
 		  ((strstr(complist, "packed") ? CMF_PACKED : 0) |
 		   (strstr(complist, "rows")   ? CMF_ROWS   : 0)) : 0));
-    cm->mode = 0;
-    cm->modec = '\0';
+    cm->mode = cm->fmode = 0;
+    cm->modec = cm->fmodec = '\0';
     if ((flags & CMF_FILE) && orig[0] && orig[strlen(orig) - 1] != '/') {
         struct stat buf;
 	char *pb;
@@ -2799,6 +2799,11 @@
             if ((cm->modec = file_type(buf.st_mode)) == ' ')
                 cm->modec = '\0';
         }
+        if (!ztat(pb, &buf, 0)) {
+            cm->fmode = buf.st_mode;
+            if ((cm->fmodec = file_type(buf.st_mode)) == ' ')
+                cm->fmodec = '\0';
+        }
     }
     if ((*compqstack == QT_BACKSLASH && compqstack[1]) ||
 	(autoq && *compqstack && compqstack[1] == QT_BACKSLASH))
@@ -3208,6 +3213,8 @@
     r->disp = ztrdup(m->disp);
     r->mode = m->mode;
     r->modec = m->modec;
+    r->fmode = m->fmode;
+    r->fmodec = m->fmodec;
 
     return r;
 }
Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.113
diff -u -r1.113 complist.c
--- Src/Zle/complist.c	22 Apr 2008 15:08:13 -0000	1.113
+++ Src/Zle/complist.c	6 May 2008 15:49:16 -0000
@@ -108,12 +108,6 @@
  * as mtab and mmtabp.
  */
 static Cmgroup *mgtab, *mgtabp;
-/*
- * Contains information about the colours to be used for entries.
- * Sometimes mcolors is passed as an argument even though it's
- * available to all the functions.
- */
-static struct listcols mcolors;
 #ifdef DEBUG
 /*
  * Allow us to keep track of pointer arithmetic for mgtab; could
@@ -248,12 +242,26 @@
 
 typedef struct listcols *Listcols;
 
+/* values for listcol flags */
+enum {
+    /* ln=target:  follow symlinks to determine highlighting */
+    LC_FOLLOW_SYMLINKS = 0x0001
+};
+
 struct listcols {
     Filecol files[NUM_COLS];	/* strings for file types */
     Patcol pats;		/* strings for patterns */
     Extcol exts;		/* strings for extensions */
+    int flags;			/* special settings, see above */
 };
 
+/*
+ * Contains information about the colours to be used for entries.
+ * Sometimes mcolors is passed as an argument even though it's
+ * available to all the functions.
+ */
+static struct listcols mcolors;
+
 /* Combined length of LC and RC, maximum length of capability strings. */
 
 static int lr_caplen, max_caplen;
@@ -428,24 +436,33 @@
 	for (i = 0, nn = colnames; *nn; i++, nn++)
 	    if (!strcmp(n, *nn))
 		break;
-	p = getcolval(s, 0);
-	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 = mcolors.files[i])) {
-		while (fo->next)
-		    fo = fo->next;
-		fo->next = fc;
-	    } else
-		mcolors.files[i] = fc;
+	/*
+	 * special case:  highlighting link targets
+	 */
+	if (i == COL_LN && strpfx("target", s) &&
+	    (s[6] == ':' || !s[6])) {
+	    mcolors.flags |= LC_FOLLOW_SYMLINKS;
+	    p = s + 6;
+	} else {
+	    p = getcolval(s, 0);
+	    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 = mcolors.files[i])) {
+		    while (fo->next)
+			fo = fo->next;
+		    fo->next = fc;
+		} else
+		    mcolors.files[i] = fc;
+	    }
+	    if (*p)
+		*p++ = '\0';
 	}
-	if (*p)
-	    *p++ = '\0';
 	return p;
     }
 }
@@ -474,6 +491,7 @@
     int i, l;
 
     max_caplen = lr_caplen = 0;
+    mcolors.flags = 0;
     queue_signals();
     if (!(s = getsparam("ZLS_COLORS")) &&
 	!(s = getsparam("ZLS_COLOURS"))) {
@@ -1685,7 +1703,7 @@
 	}
 	zcoff();
     } else {
-	int mx;
+	int mx, modec;
 
 	if (g->widths) {
 	    int i;
@@ -1733,8 +1751,13 @@
 	    zcputs(g->name, COL_HI);
 	else if (mselect >= 0 && (m->flags & (CMF_MULT | CMF_FMULT)))
 	    zcputs(g->name, COL_DU);
-	else if (m->mode)
-	    subcols = putfilecol(g->name, m->str, m->mode);
+	else if (m->mode) {
+	    if (mcolors.flags & LC_FOLLOW_SYMLINKS) {
+		subcols = putfilecol(g->name, m->str, m->fmode);
+	    } else {
+		subcols = putfilecol(g->name, m->str, m->mode);
+	    }
+	}
 	else
 	    subcols = putmatchcol(g->name, (m->disp ? m->disp : m->str));
 
@@ -1747,12 +1770,13 @@
 	len = ZMB_nicewidth(m->disp ? m->disp : m->str);
 	mlprinted = len ? (len-1) / columns : 0;
 
-	if ((g->flags & CGF_FILES) && m->modec) {
+	modec = (mcolors.flags & LC_FOLLOW_SYMLINKS) ? m->fmodec : m->modec;
+	if ((g->flags & CGF_FILES) && modec) {
 	    if (m->gnum != mselect) {
 		zcoff();
 		zcputs(g->name, COL_TC);
 	    }
-	    putc(m->modec, shout);
+	    putc(modec, shout);
 	    len++;
         }
 	if ((len = width - len - 2) > 0) {
@@ -2556,6 +2580,15 @@
 	    s->origcs = origcs;
 	    s->origll = origll;
             s->status = dupstring(status);
+	    /*
+	     * with just the slightest hint of a note of infuriation:
+	     * mode here is the menu mode, not the file mode, despite
+	     * the fact we're in a file dealing with file highlighting;
+	     * but that's OK, because s is a menu stack entry, despite
+	     * the fact we're in a function declaring s as char *.
+	     * anyway, in functions we really mean *mode* it's
+	     * called m, to be clear.
+	     */
             s->mode = mode;
 	    menucmp = menuacc = hasoldlist = 0;
 	    minfo.cur = NULL;
@@ -2674,6 +2707,7 @@
 	    s->origcs = origcs;
 	    s->origll = origll;
             s->status = dupstring(status);
+	    /* see above */
             s->mode = mode;
 	    accept_last();
 	    handleundo();



-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



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