summaryrefslogtreecommitdiff
path: root/Src/Zle/computil.c
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2001-07-18 13:10:07 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2001-07-18 13:10:07 +0000
commit8c1b953b5a6c49d47f55d311d16852f94d2ebeed (patch)
treebbd14925f61c99b3aa89067b89e82abbae4f253e /Src/Zle/computil.c
parent40f651019666eba2c3c8a53055f16d28f6ed9385 (diff)
downloadzsh-8c1b953b5a6c49d47f55d311d16852f94d2ebeed.tar.gz
zsh-8c1b953b5a6c49d47f55d311d16852f94d2ebeed.zip
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 (15407)
Diffstat (limited to 'Src/Zle/computil.c')
-rw-r--r--Src/Zle/computil.c323
1 files changed, 206 insertions, 117 deletions
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;
}