From 7f7497c531841c7fa53bfa2618c7d5592abddfda Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 2 Dec 1999 11:32:09 +0000 Subject: zsh-workers/8851 --- Doc/Zsh/mod_complist.yo | 18 ++++ Src/Zle/compcore.c | 7 +- Src/Zle/complist.c | 262 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 224 insertions(+), 63 deletions(-) diff --git a/Doc/Zsh/mod_complist.yo b/Doc/Zsh/mod_complist.yo index ca8fa2be3..54211674c 100644 --- a/Doc/Zsh/mod_complist.yo +++ b/Doc/Zsh/mod_complist.yo @@ -76,6 +76,24 @@ enditem() 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(*)', diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 875674023..1bc1fd86f 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -445,9 +445,8 @@ before_complete(Hookdef dummy, int *lst) /* 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 @@ permmatches(int last) 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 @@ freematches(Cmgroup g) } free(g->expls); } + zsfree(g->name); free(g); g = n; diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 612191913..1f8cd0fa7 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -74,11 +74,33 @@ static char *defcols[] = { "\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 @@ struct extcol { 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 @@ getcolval(char *s) 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 @@ getcoldef(Listcols c, char *s) *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 @@ getcoldef(Listcols c, char *s) 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 @@ getcols(Listcols c) 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 @@ getcols(Listcols c) /* 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 @@ static struct listcols mcolors; /* 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->files[COL_LC]->col); + strcat(buf, cap); + strcat(buf, c->files[COL_RC]->col); - strcpy(buf, c->cols[COL_LC]); - strcat(buf, cap); - strcat(buf, c->cols[COL_RC]); + 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 @@ zcputs(Listcols c, int colour) 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 @@ putcolstr(Listcols c, char *n, mode_t m) else colour = COL_FI; - zcputs(c, colour); - return; + zcputs(c, group, colour); } static void @@ -340,10 +482,10 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, 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 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, 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 @@ complistmatches(Hookdef dummy, Chdata dat) 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; -- cgit 1.4.1