summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Completion/Base/Utility/_describe14
-rw-r--r--Completion/Zsh/Command/_zstyle1
-rw-r--r--Doc/Zsh/compsys.yo14
-rw-r--r--Src/Zle/complist.c12
-rw-r--r--Src/Zle/compresult.c71
-rw-r--r--Src/Zle/computil.c323
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;
}