From dbe5fd93a7f29a6f800d470fff3c1b946ec3fdb4 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 6 May 2008 16:01:18 +0000 Subject: 24951: implement ZLS_COLORS ln=target --- ChangeLog | 3 ++ Doc/Zsh/mod_complist.yo | 4 ++- Src/Zle/comp.h | 2 ++ Src/Zle/compcore.c | 11 ++++-- Src/Zle/complist.c | 90 ++++++++++++++++++++++++++++++++++--------------- 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76cd874f6..67d6aeb62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ 2008-05-06 Peter Stephenson + * 24951: Doc/Zsh/mod_complist, Src/Zle/comp.h, Src/Zle/compcore.c, + Src/Zle/complist.c: implement ZLS_COLORS ln=target. + * 24937, 24938: Dag-Erling Smørgrav : configure.ac: improved version of 24972. diff --git a/Doc/Zsh/mod_complist.yo b/Doc/Zsh/mod_complist.yo index 9d3e68dc9..f918a4345 100644 --- a/Doc/Zsh/mod_complist.yo +++ b/Doc/Zsh/mod_complist.yo @@ -37,7 +37,9 @@ item(tt(di 32))( 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) diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 1b1530492..bcad3df05 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -114,6 +114,8 @@ struct cmatch { 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 */ diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index e66c1f71d..79de193cd 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -2784,8 +2784,8 @@ add_match_data(int alt, char *str, char *orig, Cline line, (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 @@ add_match_data(int alt, char *str, char *orig, Cline line, 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 @@ dupmatch(Cmatch m, int nbeg, int nend) r->disp = ztrdup(m->disp); r->mode = m->mode; r->modec = m->modec; + r->fmode = m->fmode; + r->fmodec = m->fmodec; return r; } diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 1543a1506..9f4cbdeaa 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -108,12 +108,6 @@ static int mtab_been_reallocated; * 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 @@ struct extcol { 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 @@ getcoldef(char *s) 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 @@ getcols() 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width) } zcoff(); } else { - int mx; + int mx, modec; if (g->widths) { int i; @@ -1733,8 +1751,13 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width) 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width) 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 @@ domenuselect(Hookdef dummy, Chdata dat) 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 @@ domenuselect(Hookdef dummy, Chdata dat) s->origcs = origcs; s->origll = origll; s->status = dupstring(status); + /* see above */ s->mode = mode; accept_last(); handleundo(); -- cgit 1.4.1