diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Completion/Base/Utility/_describe | 14 | ||||
-rw-r--r-- | Completion/Zsh/Command/_zstyle | 1 | ||||
-rw-r--r-- | Doc/Zsh/compsys.yo | 14 | ||||
-rw-r--r-- | Src/Zle/complist.c | 12 | ||||
-rw-r--r-- | Src/Zle/compresult.c | 71 | ||||
-rw-r--r-- | Src/Zle/computil.c | 323 |
7 files changed, 284 insertions, 159 deletions
diff --git a/ChangeLog b/ChangeLog index 716f73120..68e6f8631 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2001-07-18 Sven Wischnowsky <wischnow@zsh.org> + * 15407: Completion/Base/Utility/_describe, + Completion/Zsh/Command/_zstyle, Doc/Zsh/compsys.yo, + Src/Zle/complist.c, Src/Zle/compresult.c, Src/Zle/computil.c: + add list-grouped option to make options and such be grouped + together if they have the same description; matches with + line-display strings can be hidden; hi and du capabalities in + complist are only used if set by the user + * 15402 (Akinora Musha): Completion/Unix/Command/_cvs: add support for -R option on BSDs diff --git a/Completion/Base/Utility/_describe b/Completion/Base/Utility/_describe index a658d16df..a58954f47 100644 --- a/Completion/Base/Utility/_describe +++ b/Completion/Base/Utility/_describe @@ -2,8 +2,8 @@ # This can be used to add options or values with descriptions as matches. -local _opt _expl _tmps _tmpd _tmpmd _tmpms _ret=1 _showd _nm _hide _args -local _type=values _descr +local _opt _expl _tmps _tmpd _tmph _tmpmd _tmpms _tmpmh +local _type=values _descr _ret=1 _showd _nm _hide _args _grp # Get the option. @@ -21,6 +21,11 @@ fi # Do the tests. `showd' is set if the descriptions should be shown. zstyle -T ":completion:${curcontext}:$_type" verbose && _showd=yes +if zstyle -T ":completion:${curcontext}:$_type" list-grouped; then + _grp=(-g) +else + _grp=() +fi _descr="$1" shift @@ -33,12 +38,12 @@ while _tags; do while _next_label "$_type" _expl "$_descr"; do if [[ -n "$_showd" ]]; then - compdescribe -I ' -- ' "$@" + compdescribe -I ' -- ' "$_grp[@]" "$@" else compdescribe -i "$@" fi - while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do + while compdescribe -g _args _tmpd _tmpmd _tmph _tmpmh _tmps _tmpms; do # See if we should remove the option prefix characters. @@ -53,6 +58,7 @@ while _tags; do fi compadd "$_args[@]" "$_expl[@]" -ld _tmpd -a _tmpmd && _ret=0 + compadd -n "$_args[@]" "$_expl[@]" -ld _tmph -a _tmpmh && _ret=0 compadd "$_args[@]" "$_expl[@]" -d _tmps -a _tmpms && _ret=0 done done diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index 37590f0d9..c72109433 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -55,6 +55,7 @@ styles=( last-prompt c:bool list c:listwhen list-colors c: + list-grouped c:bool list-packed c:bool list-prompt c: list-rows-first c:bool diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index c5260245a..22352b550 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -1508,6 +1508,17 @@ example(zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}) The default colors are the same as for the GNU tt(ls) command and can be obtained by setting the style to an empty string (i.e. tt('')). ) +kindex(list-grouped, completion style) +item(tt(list-grouped))( +If this style is `true' (the default), the completion system will try to +make some completion listings more compact by grouping matches together. +For example, options for commands that have the same description (which +are shown because the tt(verbose) style is set to `true') will have only +one entry in the list, showing all options that can be used to select +the specific behaviour. When menu selection is done on such a list, the +matches will appear as separate entries in the list to be able to select +each of them. +) kindex(list-packed, completion style) item(tt(list-packed))( Like the tt(list-colors) style, this is tested with the tt(default) @@ -3463,6 +3474,9 @@ the tt(prefix-hidden), tt(prefix-needed) and tt(verbose) styles to find out if the strings should be added at all and if the descriptions should be shown. Without the `tt(-o)' option, only the tt(verbose) style is used. +If selected by the tt(list-grouped) style, strings with the same +description will be added in a way that they appear together in the list. + tt(_describe) uses the tt(_all_labels) function to generate the matches, so it does not need to appear inside a loop over tag labels. ) diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index f76e54116..94fd2cc56 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -77,7 +77,7 @@ static char *colnames[] = { static char *defcols[] = { "0", "0", "1;31", "1;36", "33", "1;35", "1;33", "1;33", "1;32", NULL, - "\033[", "m", NULL, "0", "0", "7", "0", "0" + "\033[", "m", NULL, "0", "0", "7", NULL, NULL }; /* This describes a terminal string for a file type. */ @@ -444,6 +444,7 @@ zcputs(Listcols c, char *group, int colour) return; } + zlrputs(c, "0"); } /* Turn off colouring. */ @@ -1170,7 +1171,8 @@ compprintlist(int showall) p = g->matches; for (; (m = *p); p++) { - if (m->disp && (m->flags & CMF_DISPLINE)) { + if (m->disp && (m->flags & CMF_DISPLINE) && + (showall || !(m->flags & (CMF_HIDE|CMF_NOLIST)))) { if (pnl) { if (dolistnl(ml) && compprintnl(ml)) goto end; @@ -1412,9 +1414,11 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, mgtabp = mgtab + mm; mmlen = mcols; zcputs(&mcolors, g->name, COL_MA); - } else if (m->flags & CMF_NOLIST) + } else if ((m->flags & CMF_NOLIST) && + mcolors.files[COL_HI] && mcolors.files[COL_HI]->col) zcputs(&mcolors, g->name, COL_HI); - else if (mselect >= 0 && (m->flags & (CMF_MULT | CMF_FMULT))) + else if (mselect >= 0 && (m->flags & (CMF_MULT | CMF_FMULT)) && + mcolors.files[COL_DU] && mcolors.files[COL_DU]->col) zcputs(&mcolors, g->name, COL_DU); else subcols = putmatchcol(&mcolors, g->name, m->disp); diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index c1da0fbff..0e7bbedba 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -1443,44 +1443,46 @@ calclist(int showall) } m->flags &= ~CMF_HIDE; - if (m->disp) { - if (m->flags & CMF_DISPLINE) { - nlines += 1 + printfmt(m->disp, 0, 0, 0); - g->flags |= CGF_HASDL; - } else { - l = niceztrlen(m->disp); - ndisp++; - if (l > glong) - glong = l; - if (l < gshort) - gshort = l; - totl += l; - mlens[m->gnum] = l; - } - nlist++; - if (!(m->flags & CMF_PACKED)) - g->flags &= ~CGF_PACKED; - if (!(m->flags & CMF_ROWS)) - g->flags &= ~CGF_ROWS; - } else if (showall || !(m->flags & (CMF_NOLIST | CMF_MULT))) { + if (showall || !(m->flags & (CMF_NOLIST | CMF_MULT))) { if ((m->flags & (CMF_NOLIST | CMF_MULT)) && (!m->str || !*m->str)) { m->flags |= CMF_HIDE; continue; } - l = niceztrlen(m->str); - ndisp++; - if (l > glong) - glong = l; - if (l < gshort) - gshort = l; - totl += l; - mlens[m->gnum] = l; - nlist++; - if (!(m->flags & CMF_PACKED)) - g->flags &= ~CGF_PACKED; - if (!(m->flags & CMF_ROWS)) - g->flags &= ~CGF_ROWS; + if (m->disp) { + if (m->flags & CMF_DISPLINE) { + nlines += 1 + printfmt(m->disp, 0, 0, 0); + g->flags |= CGF_HASDL; + } else { + l = niceztrlen(m->disp); + ndisp++; + if (l > glong) + glong = l; + if (l < gshort) + gshort = l; + totl += l; + mlens[m->gnum] = l; + } + nlist++; + if (!(m->flags & CMF_PACKED)) + g->flags &= ~CGF_PACKED; + if (!(m->flags & CMF_ROWS)) + g->flags &= ~CGF_ROWS; + } else { + l = niceztrlen(m->str); + ndisp++; + if (l > glong) + glong = l; + if (l < gshort) + gshort = l; + totl += l; + mlens[m->gnum] = l; + nlist++; + if (!(m->flags & CMF_PACKED)) + g->flags &= ~CGF_PACKED; + if (!(m->flags & CMF_ROWS)) + g->flags &= ~CGF_ROWS; + } } else hidden = 1; } @@ -1972,7 +1974,8 @@ printlist(int over, CLPrintFunc printm, int showall) if (g->flags & CGF_HASDL) { for (p = g->matches; (m = *p); p++) - if (m->disp && (m->flags & CMF_DISPLINE)) { + if (m->disp && (m->flags & CMF_DISPLINE) && + (showall || !(m->flags & (CMF_HIDE|CMF_NOLIST)))) { if (pnl) { putc('\n', shout); pnl = 0; diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 870bbcce8..522c6356d 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -31,59 +31,42 @@ #include "computil.pro" -/* Help for `_display'. */ - -/* Calculation state. */ - -typedef struct cdisp *Cdisp; - -struct cdisp { - int pre; /* prefix length */ - int suf; /* suffix length */ - int colon; /* number of strings with descriptions */ -}; - -/* Calculate longest prefix and suffix and count the strings with - * descriptions. */ - -static void -cdisp_calc(Cdisp disp, char **args) -{ - char *cp; - int i, nbc; - - for (; *args; args++) { - for (nbc = 0, cp = *args; *cp && *cp != ':'; cp++) - if (*cp == '\\' && cp[1]) - cp++, nbc++; - if (*cp == ':' && cp[1]) { - disp->colon++; - if ((i = cp - *args - nbc) > disp->pre) - disp->pre = i; - if ((i = strlen(cp + 1)) > disp->suf) - disp->suf = i; - } - } -} - -/* Help fuer `_describe'. */ +/* Help for `_describe'. */ typedef struct cdset *Cdset; +typedef struct cdstr *Cdstr; struct cdstate { int showd; /* != 0 if descriptions should be shown */ char *sep; /* the separator string */ + int slen; /* its length */ Cdset sets; /* the sets of matches */ - struct cdisp disp; /* used to calculate the alignment */ + int pre; /* longest prefix (before description) */ + int suf; /* longest suffix (description) */ +}; + +struct cdstr { + Cdstr next; /* the next one in this set */ + char *str; /* the string to display */ + char *desc; /* the description or NULL */ + char *match; /* the match to add */ + Cdstr other; /* next string with the same description */ + int kind; /* 0: not in a group, 1: the first, 2: other */ }; struct cdset { Cdset next; /* guess what */ char **opts; /* the compadd-options */ - char **strs; /* the display-strings */ - char **matches; /* the matches (or NULL) */ + Cdstr strs; /* the strings/matches */ + int count; /* number of matches in this set */ + int desc; /* number of matches with description */ }; +/* Maximum string length when used with descriptions. */ + +#define CD_MAXLEN 20 + + static struct cdstate cd_state; static int cd_parsed = 0; @@ -91,26 +74,116 @@ static void freecdsets(Cdset p) { Cdset n; + Cdstr s, sn; for (; p; p = n) { n = p->next; if (p->opts) freearray(p->opts); - if (p->strs) - freearray(p->strs); - if (p->matches) - freearray(p->matches); + for (s = p->strs; s; s = sn) { + sn = s->next; + zsfree(s->str); + zsfree(s->desc); + if (s->match != s->str) + zsfree(s->match); + zfree(s, sizeof(*s)); + } zfree(p, sizeof(*p)); } } +/* Find matches with same descriptions and group them. */ + +static void +cd_group() +{ + Cdset set1, set2; + Cdstr str1, str2, *strp; + int yep = 0; + char *buf; + + for (set1 = cd_state.sets; set1; set1 = set1->next) { + for (str1 = set1->strs; str1; str1 = str1->next) { + if (!str1->desc || str1->kind != 0) + continue; + + strp = &(str1->other); + + for (set2 = set1; set2; set2 = set2->next) + for (str2 = (set2 == set1 ? str1->next : set2->strs); + str2; str2 = str2->next) + if (str2->desc && !strcmp(str1->desc, str2->desc)) { + str1->kind = 1; + str2->kind = 2; + zsfree(str2->desc); + str2->desc = ztrdup("|"); + *strp = str2; + strp = &(str2->other); + yep = 1; + } + *strp = NULL; + } + } + if (!yep) + return; + + for (set1 = cd_state.sets; set1; set1 = set1->next) { + for (str1 = set1->strs; str1; str1 = str1->next) { + if (str1->kind != 1) + continue; + + buf = str1->str; + for (str2 = str1->other; str2; str2 = str2->other) + buf = zhtricat(buf, ", ", str2->str); + + for (str2 = str1; str2; str2 = str2->other) { + if (str2->str == str2->match) + str2->match = ztrdup(str2->match); + zsfree(str2->str); + str2->str = ztrdup(buf); + } + } + } +} + +/* Calculate longest prefix and suffix and count the strings with + * descriptions. */ + +static void +cd_calc() +{ + Cdset set; + Cdstr str; + int l; + + cd_state.pre = cd_state.suf = 0; + + for (set = cd_state.sets; set; set = set->next) { + set->count = set->desc = 0; + for (str = set->strs; str; str = str->next) { + set->count++; + if ((l = strlen(str->str)) > cd_state.pre) + cd_state.pre = l; + if (str->desc) { + set->desc++; + if ((l = strlen(str->desc)) > cd_state.suf) + cd_state.suf = l; + } + } + } + if (cd_state.pre > 20) + cd_state.pre = 20; +} + /* Initialisation. Store and calculate the string and matches and so on. */ static int cd_init(char *nam, char *sep, char **args, int disp) { Cdset *setp, set; + Cdstr *strp, str; char **ap, *tmp; + int grp = 0; if (cd_parsed) { zsfree(cd_state.sep); @@ -119,29 +192,57 @@ cd_init(char *nam, char *sep, char **args, int disp) } setp = &(cd_state.sets); cd_state.sep = ztrdup(sep); + cd_state.slen = ztrlen(sep); cd_state.sets = NULL; - cd_state.disp.pre = cd_state.disp.suf = cd_state.disp.colon = 0; cd_state.showd = disp; + if (*args && !strcmp(*args, "-g")) { + args++; + grp = 1; + } while (*args) { *setp = set = (Cdset) zcalloc(sizeof(*set)); setp = &(set->next); + *setp = NULL; + set->opts = NULL; + set->strs = NULL; if (!(ap = get_user_var(*args))) { zwarnnam(nam, "invalid argument: %s", *args, 0); + zsfree(cd_state.sep); + freecdsets(cd_state.sets); return 1; } - set->strs = zarrdup(ap); + for (strp = &(set->strs); *ap; ap++) { + *strp = str = (Cdstr) zalloc(sizeof(*str)); + strp = &(str->next); - if (disp) - cdisp_calc(&(cd_state.disp), set->strs); + str->kind = 0; + str->other = NULL; + + for (tmp = *ap; *tmp && *tmp != ':'; tmp++) + if (*tmp == '\\' && tmp[1]) + tmp++; + + if (*tmp) + str->desc = ztrdup(rembslash(tmp + 1)); + else + str->desc = NULL; + *tmp = '\0'; + str->str = str->match = ztrdup(rembslash(*ap)); + } + str->next = NULL; if (*++args && **args != '-') { if (!(ap = get_user_var(*args))) { zwarnnam(nam, "invalid argument: %s", *args, 0); + zsfree(cd_state.sep); + freecdsets(cd_state.sets); return 1; } - set->matches = zarrdup(ap); + for (str = set->strs; str && *ap; str = str->next, ap++) + str->match = ztrdup(*ap); + args++; } for (ap = args; *args && @@ -154,6 +255,11 @@ cd_init(char *nam, char *sep, char **args, int disp) if ((*args = tmp)) args++; } + if (disp && grp) + cd_group(); + + cd_calc(); + cd_parsed = 1; return 0; } @@ -166,77 +272,60 @@ cd_get(char **params) Cdset set; if ((set = cd_state.sets)) { - char **sd, **sdp, **md, **mdp, **ss, **ssp, **ms, **msp; - char **p, **mp, *cp, *copy, *cpp, oldc; - int dl = 1, sl = 1, sepl = strlen(cd_state.sep); - int pre = cd_state.disp.pre, suf = cd_state.disp.suf; - VARARR(char, buf, pre + suf + sepl + 1); - - for (p = set->strs; *p; p++) - if (cd_state.showd) { - for (cp = *p; *cp && *cp != ':'; cp++) - if (*cp == '\\' && cp[1]) - cp++; - if (*cp == ':' && cp[1]) - dl++; - else - sl++; - } else - sl++; - - sd = (char **) zalloc(dl * sizeof(char *)); - ss = (char **) zalloc(sl * sizeof(char *)); - md = (char **) zalloc(dl * sizeof(char *)); - ms = (char **) zalloc(sl * sizeof(char *)); - - if (cd_state.showd) { - memcpy(buf + pre, cd_state.sep, sepl); - suf = pre + sepl; - } - - /* Build the aligned display strings. */ - - for (sdp = sd, ssp = ss, mdp = md, msp = ms, - p = set->strs, mp = set->matches; *p; p++) { - copy = dupstring(*p); - for (cp = cpp = copy; *cp && *cp != ':'; cp++) { - if (*cp == '\\' && cp[1]) - cp++; - *cpp++ = *cp; - } - oldc = *cpp; - *cpp = '\0'; - if (((cpp == cp && oldc == ':') || *cp == ':') && cp[1] && - cd_state.showd) { - memset(buf, ' ', pre); - memcpy(buf, copy, (cpp - copy)); - strcpy(buf + suf, cp + 1); - *sdp++ = ztrdup(buf); - if (mp) { - *mdp++ = ztrdup(*mp); - if (*mp) - mp++; - } else - *mdp++ = ztrdup(copy); - } else { - *ssp++ = ztrdup(copy); - if (mp) { - *msp++ = ztrdup(*mp); - if (*mp) - mp++; - } else - *msp++ = ztrdup(copy); - } - } - *sdp = *ssp = *mdp = *msp = NULL; + char **sd, **sdp, **md, **mdp, **sh, **shp, **mh, **mhp; + char **ss, **ssp, **ms, **msp; + Cdstr str; + VARARR(char, buf, cd_state.pre + cd_state.suf + cd_state.slen + 1); + char *sufp = NULL, *disp; + + if (cd_state.showd) { + memcpy(buf + cd_state.pre, cd_state.sep, cd_state.slen); + sufp = buf + cd_state.pre + cd_state.slen; + } + sd = (char **) zalloc((set->desc + 1) * sizeof(char *)); + md = (char **) zalloc((set->desc + 1) * sizeof(char *)); + sh = (char **) zalloc((set->desc + 1) * sizeof(char *)); + mh = (char **) zalloc((set->desc + 1) * sizeof(char *)); + ss = (char **) zalloc((set->count + 1) * sizeof(char *)); + ms = (char **) zalloc((set->count + 1) * sizeof(char *)); + + for (sdp = sd, mdp = md, shp = sh, mhp = mh, + ssp = ss, msp = ms, str = set->strs; + str; + str = str->next) { + if (cd_state.showd && str->desc) { + if (strlen(str->str) > CD_MAXLEN) + disp = tricat(str->str, cd_state.sep, str->desc); + else { + strcpy(sufp, str->desc); + memset(buf, ' ', cd_state.pre); + memcpy(buf, str->str, strlen(str->str)); + disp = ztrdup(buf); + } + if (strlen(disp) >= columns) + disp[columns - 1] = '\0'; - p = zarrdup(set->opts); + if (str->kind == 2) { + *shp++ = disp; + *mhp++ = ztrdup(str->match); + } else { + *sdp++ = disp; + *mdp++ = ztrdup(str->match); + } + } else { + *ssp++ = ztrdup(str->str); + *msp++ = ztrdup(str->match); + } + } + *sdp = *mdp = *shp = *mhp = *ssp = *msp = NULL; - setaparam(params[0], p); + setaparam(params[0], zarrdup(set->opts)); setaparam(params[1], sd); setaparam(params[2], md); - setaparam(params[3], ss); - setaparam(params[4], ms); + setaparam(params[3], sh); + setaparam(params[4], mh); + setaparam(params[5], ss); + setaparam(params[6], ms); cd_state.sets = set->next; set->next = NULL; @@ -268,8 +357,8 @@ bin_compdescribe(char *nam, char **args, char *ops, int func) if (cd_parsed) { int n = arrlen(args); - if (n != 6) { - zwarnnam(nam, (n < 6 ? "not enough arguments" : + if (n != 8) { + zwarnnam(nam, (n < 8 ? "not enough arguments" : "too many arguments"), NULL, 0); return 1; } |