diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 3 | ||||
-rw-r--r-- | Src/Zle/compcore.c | 69 | ||||
-rw-r--r-- | Src/Zle/complete.c | 18 | ||||
-rw-r--r-- | Src/Zle/complist.c | 7 | ||||
-rw-r--r-- | Src/Zle/compresult.c | 50 | ||||
-rw-r--r-- | Src/Zle/computil.c | 456 |
6 files changed, 469 insertions, 134 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 22029d511..c06e7aa7e 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -85,6 +85,7 @@ struct cmgroup { #define CGF_UNIQCON 16 /* remove consecutive duplicates */ #define CGF_PACKED 32 /* LIST_PACKED for this group */ #define CGF_ROWS 64 /* LIST_ROWS_FIRST for this group */ +#define CGF_FILES 128 /* contains file names */ /* This is the struct used to hold matches. */ @@ -125,6 +126,7 @@ struct cmatch { #define CMF_MULT (1<<11) /* string appears more than once */ #define CMF_FMULT (1<<12) /* first of multiple equal strings */ #define CMF_ALL (1<<13) /* a match representing all other matches */ +#define CMF_DUMMY (1<<14) /* unselectable dummy match */ /* Stuff for completion matcher control. */ @@ -264,6 +266,7 @@ struct cadata { char *dpar; /* array to delete non-matches in (-D) */ char *disp; /* array with display lists (-d) */ char *mesg; /* message to show unconditionally (-x) */ + int dummies; /* add that many dummy matches */ }; /* List data. */ diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 97ed6d58f..00dfea935 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1558,6 +1558,40 @@ get_data_arr(char *name, int keys) return ret; } +static void +addmatch(char *str, int flags, char ***dispp, int line) +{ + Cmatch cm = (Cmatch) zhalloc(sizeof(struct cmatch)); + char **disp = *dispp; + + memset(cm, 0, sizeof(struct cmatch)); + cm->str = dupstring(str); + cm->flags = (flags | + (complist ? + ((strstr(complist, "packed") ? CMF_PACKED : 0) | + (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); + if (disp) { + if (!*++disp) + disp = NULL; + if (disp) + cm->disp = dupstring(*disp); + } else if (line) { + cm->disp = dupstring(""); + cm->flags |= CMF_DISPLINE; + } + mnum++; + ainfo->count++; + if (curexpl) + curexpl->count++; + + addlinknode(matches, cm); + + newmatches = 1; + mgroup->new = 1; + + *dispp = disp; +} + /* This is used by compadd to add a couple of matches. The arguments are * the strings given via options. The last argument is the array with * the matches. */ @@ -1583,7 +1617,7 @@ addmatches(Cadata dat, char **argv) Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; Heap oldheap; - if (!*argv && !(dat->aflags & CAF_ALL)) { + if (!*argv && !dat->dummies && !(dat->aflags & CAF_ALL)) { SWITCHHEAPS(oldheap, compheap) { /* Select the group in which to store the matches. */ gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | @@ -1602,6 +1636,8 @@ addmatches(Cadata dat, char **argv) return 1; } + if (dat->dummies) + dat->aflags = dat->aflags | CAF_NOSORT | CAF_UNIQALL; for (bp = brbeg; bp; bp = bp->next) bp->curpos = ((dat->aflags & CAF_QUOTE) ? bp->pos : bp->qpos); for (bp = brend; bp; bp = bp->next) @@ -2022,35 +2058,12 @@ addmatches(Cadata dat, char **argv) if (dat->exp) addexpl(); if (!hasallmatch && (dat->aflags & CAF_ALL)) { - Cmatch cm = (Cmatch) zhalloc(sizeof(struct cmatch)); - - memset(cm, 0, sizeof(struct cmatch)); - cm->str = dupstring("<all>"); - cm->flags = (dat->flags | CMF_ALL | - (complist ? - ((strstr(complist, "packed") ? CMF_PACKED : 0) | - (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); - if (disp) { - if (!*++disp) - disp = NULL; - if (disp) - cm->disp = dupstring(*disp); - } else { - cm->disp = dupstring(""); - cm->flags |= CMF_DISPLINE; - } - mnum++; - ainfo->count++; - if (curexpl) - curexpl->count++; - - addlinknode(matches, cm); - - newmatches = 1; - mgroup->new = 1; - + addmatch("<all>", dat->flags | CMF_ALL, &disp, 1); hasallmatch = 1; } + while (dat->dummies--) + addmatch("", dat->flags | CMF_DUMMY, &disp, 0); + } SWITCHBACKHEAPS(oldheap); /* We switched back to the current heap, now restore the stack of diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 574e638ac..106e0ddab 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -435,6 +435,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; + dat.dummies = 0; for (; *argv && **argv == '-'; argv++) { if (!(*argv)[1]) { @@ -565,6 +566,23 @@ bin_compadd(char *name, char **argv, char *ops, int func) case 'l': dat.flags |= CMF_DISPLINE; break; + case 'E': + if (p[1]) { + dat.dummies = atoi(p + 1); + p = "" - 1; + } else if (argv[1]) { + argv++; + dat.dummies = atoi(*argv); + p = "" - 1; + } else { + zwarnnam(name, "number expected after -%c", NULL, *p); + return 1; + } + if (dat.dummies < 0) { + zwarnnam(name, "invalid number: %d", NULL, dat.dummies); + return 1; + } + break; case '-': argv++; goto ca_args; diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 94fd2cc56..14cb16d4c 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -1394,7 +1394,7 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, mlastm = m->gnum; if (m->disp && (m->flags & CMF_DISPLINE)) { - if (mselect >= 0) { + if (mselect >= 0 && !(m->flags & CMF_DUMMY)) { int mm = (mcols * ml), i; for (i = mcols; i--; ) { @@ -1441,7 +1441,7 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, } else mx = mc * g->width; - if (mselect >= 0) { + if (mselect >= 0 && !(m->flags & CMF_DUMMY)) { int mm = mcols * ml, i; for (i = (width ? width : mcols); i--; ) { @@ -1482,7 +1482,7 @@ clprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, len = niceztrlen(m->disp ? m->disp : m->str); mlprinted = len / columns; - if (isset(LISTTYPES) && buf) { + if ((g->flags & CGF_FILES) && buf) { if (m->gnum != mselect) { zcoff(); zcputs(&mcolors, g->name, COL_TC); @@ -1684,6 +1684,7 @@ domenuselect(Hookdef dummy, Chdata dat) noselect = 1; while ((menuacc && !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || + ((*minfo.cur)->flags & CMF_DUMMY) || (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && (!(*minfo.cur)->str || !*(*minfo.cur)->str))) do_menucmp(0); diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index 0e7bbedba..6b5d7df38 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -1160,6 +1160,7 @@ do_menucmp(int lst) } } while ((menuacc && !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || + ((*minfo.cur)->flags & CMF_DUMMY) || (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && (!(*minfo.cur)->str || !*(*minfo.cur)->str))); /* ... and insert it into the command line. */ @@ -1183,6 +1184,7 @@ reverse_menu(Hookdef dummy, void *dummy2) minfo.cur--; } while ((menuacc && !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || + ((*minfo.cur)->flags & CMF_DUMMY) || (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && (!(*minfo.cur)->str || !*(*minfo.cur)->str))); metafy_line(); @@ -1378,7 +1380,7 @@ calclist(int showall) Cmgroup g; Cmatch *p, m; Cexpl *e; - int hidden = 0, nlist = 0, nlines = 0, add = 2 + isset(LISTTYPES); + int hidden = 0, nlist = 0, nlines = 0, add; int max = 0, i; VARARR(int, mlens, nmatches + 1); @@ -1392,6 +1394,7 @@ calclist(int showall) for (g = amatches; g; g = g->next) { char **pp = g->ylist; int nl = 0, l, glong = 1, gshort = columns, ndisp = 0, totl = 0; + int hasf = 0; g->flags |= CGF_PACKED | CGF_ROWS; @@ -1437,6 +1440,8 @@ calclist(int showall) } } else if (!onlyexpl) { for (p = g->matches; (m = *p); p++) { + if (m->flags & CMF_FILE) + hasf = 1; if (menuacc && !hasbrpsfx(m, minfo.prebr, minfo.postbr)) { m->flags |= CMF_HIDE; continue; @@ -1496,6 +1501,11 @@ calclist(int showall) e++; } } + if (isset(LISTTYPES) && hasf) { + g->flags |= CGF_FILES; + add = 3; + } else + add = 2; g->totl = totl + (ndisp * add); g->dcount = ndisp; g->width = glong + add; @@ -1513,6 +1523,7 @@ calclist(int showall) int *ws, tlines, tline, tcols, maxlen, nth, width, glines; for (g = amatches; g; g = g->next) { + add = 2 + !!(g->flags & CGF_FILES); glines = 0; zfree(g->widths, 0); @@ -1523,7 +1534,8 @@ calclist(int showall) if (g->cols) { glines += (arrlen(pp) + g->cols - 1) / g->cols; if (g->cols > 1) - g->width += (max - (g->width * g->cols - add)) / g->cols; + g->width += ((max - (g->width * g->cols - add)) / + g->cols); } else { g->cols = 1; g->width = 1; @@ -1559,6 +1571,8 @@ calclist(int showall) if (!(g->flags & CGF_PACKED)) continue; + add = 2 + !!(g->flags & CGF_FILES); + ws = g->widths = (int *) zalloc(columns * sizeof(int)); memset(ws, 0, columns * sizeof(int)); tlines = g->lins; @@ -1666,7 +1680,7 @@ calclist(int showall) } else if (g->width) { if (g->flags & CGF_ROWS) { int addlen, count, tcol, maxlines = 0, llines, i; - int beg = columns / g->shortest, end = g->cols; + int beg = columns / g->shortest, end = g->cols, fe = 1; Cmatch *first; while (1) { @@ -1677,7 +1691,8 @@ calclist(int showall) count = g->dcount; count > 0; count--) { m = *p; - addlen = mlens[m->gnum] + add; + addlen = (mlens[m->gnum] + + (tcol == tcols - 1 ? 0 : add)); if (addlen > maxlen) maxlen = addlen; for (i = tcols; i && *p; i--) @@ -1706,15 +1721,21 @@ calclist(int showall) break; if (beg == end) { - beg--; - end--; + if (fe) { + beg += 2; + end += 2; + fe = 0; + } else { + beg--; + end--; + } } else if (width < columns) { if ((end = tcols) == beg - 1) end++; } else { if ((beg = tcols) - 1 == end) end++; - } + } } if (tcols > g->cols) tlines = maxlines; @@ -1723,7 +1744,7 @@ calclist(int showall) int smask = ((showall ? 0 : (CMF_NOLIST | CMF_MULT)) | CMF_HIDE); int beg = ((g->totl + columns) / columns); - int end = g->lins; + int end = g->lins, fe = 1; while (1) { tlines = (beg + end) >> 1; @@ -1755,8 +1776,14 @@ calclist(int showall) break; if (beg == end) { - beg++; - end++; + if (fe) { + beg -= 2; + end -= 2; + fe = 0; + } else { + beg++; + end++; + } } else if (width < columns) { if ((end = tlines) == beg + 1) end--; @@ -1783,6 +1810,7 @@ calclist(int showall) } } for (g = amatches; g; g = g->next) { + add = 2 + !!(g->flags & CGF_FILES); if (g->widths) { int *p, a = (max - g->totl + add) / g->cols; @@ -2152,7 +2180,7 @@ iprintm(Cmgroup g, Cmatch *mp, int mc, int ml, int lastc, int width, nicezputs(m->str, shout); len = niceztrlen(m->str); - if (isset(LISTTYPES) && buf) { + if ((g->flags & CGF_FILES) && buf) { putc(file_type(buf->st_mode), shout); len++; } diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 5c4fc3ed5..7548a87bf 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -35,6 +35,7 @@ typedef struct cdset *Cdset; typedef struct cdstr *Cdstr; +typedef struct cdrun *Cdrun; struct cdstate { int showd; /* != 0 if descriptions should be shown */ @@ -43,6 +44,11 @@ struct cdstate { Cdset sets; /* the sets of matches */ int pre; /* longest prefix (before description) */ int suf; /* longest suffix (description) */ + int maxg; /* size of largest group */ + int groups; /* number of groups */ + int descs; /* number of non-group matches with desc */ + int gpre; /* prefix length for group display */ + Cdrun runs; /* runs to report to shell code */ }; struct cdstr { @@ -50,10 +56,25 @@ struct cdstr { char *str; /* the string to display */ char *desc; /* the description or NULL */ char *match; /* the match to add */ + int len; /* length of str or match */ Cdstr other; /* next string with the same description */ int kind; /* 0: not in a group, 1: the first, 2: other */ + Cdset set; /* the set this string is in */ + Cdstr run; /* next in this run */ }; +struct cdrun { + Cdrun next; /* ... */ + int type; /* see CRT_* below */ + Cdstr strs; /* strings in this run */ + int count; /* number of strings in this run */ +}; + +#define CRT_SIMPLE 0 +#define CRT_DESC 1 +#define CRT_SPEC 2 +#define CRT_DUMMY 3 + struct cdset { Cdset next; /* guess what */ char **opts; /* the compadd-options */ @@ -62,11 +83,6 @@ struct cdset { int desc; /* number of matches with description */ }; -/* Maximum string length when used with descriptions. */ - -#define CD_MAXLEN 30 - - static struct cdstate cd_state; static int cd_parsed = 0; @@ -75,6 +91,7 @@ freecdsets(Cdset p) { Cdset n; Cdstr s, sn; + Cdrun r, rn; for (; p; p = n) { n = p->next; @@ -88,6 +105,10 @@ freecdsets(Cdset p) zsfree(s->match); zfree(s, sizeof(*s)); } + for (r = cd_state.runs; r; r = rn) { + rn = r->next; + zfree(r, sizeof(*r)); + } zfree(p, sizeof(*p)); } } @@ -99,14 +120,14 @@ cd_group() { Cdset set1, set2; Cdstr str1, str2, *strp; - int yep = 0; - char *buf; + int num; for (set1 = cd_state.sets; set1; set1 = set1->next) { for (str1 = set1->strs; str1; str1 = str1->next) { if (!str1->desc || str1->kind != 0) continue; + num = 1; strp = &(str1->other); for (set2 = set1; set2; set2 = set2->next) @@ -115,33 +136,18 @@ cd_group() if (str2->desc && !strcmp(str1->desc, str2->desc)) { str1->kind = 1; str2->kind = 2; - zsfree(str2->desc); - str2->desc = ztrdup("|"); + num++; *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); + if (num > 1) + cd_state.groups++; + else + cd_state.descs++; - for (str2 = str1; str2; str2 = str2->other) { - if (str2->str == str2->match) - str2->match = ztrdup(str2->match); - zsfree(str2->str); - str2->str = ztrdup(buf); - } + if (num > cd_state.maxg) + cd_state.maxg = num; } } } @@ -171,14 +177,172 @@ cd_calc() } } } - if (cd_state.pre > CD_MAXLEN) - cd_state.pre = CD_MAXLEN; +} + +static int +cd_sort(const void *a, const void *b) +{ + return strcmp((*((Cdstr *) a))->str, (*((Cdstr *) b))->str); +} + +static void +cd_prep() +{ + Cdrun run, *runp; + Cdset set; + Cdstr str, *strp; + + runp = &(cd_state.runs); + + if (cd_state.groups) { + int lines = cd_state.groups + cd_state.descs; + VARARR(Cdstr, grps, lines); + VARARR(int, wids, cd_state.maxg); + Cdstr gs, gp, gn, *gpp; + int i, j; + + memset(wids, 0, cd_state.maxg * sizeof(int)); + strp = grps; + + for (set = cd_state.sets; set; set = set->next) + for (str = set->strs; str; str = str->next) { + if (str->kind != 1) { + if (!str->kind && str->desc) { + str->other = NULL; + *strp++ = str; + } + continue; + } + gs = str; + gs->kind = 2; + gp = str->other; + gs->other = NULL; + for (; gp; gp = gn) { + gn = gp->other; + gp->other = NULL; + for (gpp = &gs; *gpp && (*gpp)->len > gp->len; + gpp = &((*gpp)->other)); + gp->other = *gpp; + *gpp = gp; + } + for (gp = gs, i = 0; gp; gp = gp->other, i++) + if (gp->len > wids[i]) + wids[i] = gp->len; + + *strp++ = gs; + } + + qsort(grps, lines, sizeof(Cdstr), cd_sort); + + for (i = lines, strp = grps; i; i--, strp++) { + for (j = 0, gs = *strp; gs->other; gs = gs->other, j++) { + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_SPEC; + run->strs = gs; + gs->run = NULL; + run->count = 1; + } + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_DUMMY + cd_state.maxg - j - 1; + run->strs = gs; + gs->run = NULL; + run->count = 1; + } + for (set = cd_state.sets; set; set = set->next) { + for (i = 0, gs = NULL, gpp = &gs, str = set->strs; + str; str = str->next) { + if (str->kind || str->desc) + continue; + + i++; + *gpp = str; + gpp = &(str->run); + } + *gpp = NULL; + if (i) { + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_SIMPLE; + run->strs = gs; + run->count = i; + } + } + cd_state.gpre = 0; + for (i = 0; i < cd_state.maxg; i++) + cd_state.gpre += wids[i] + 2; + } else if (cd_state.showd) { + for (set = cd_state.sets; set; set = set->next) { + if (set->desc) { + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_DESC; + strp = &(run->strs); + for (str = set->strs; str; str = str->next) + if (str->desc) { + *strp = str; + strp = &(str->run); + } + *strp = NULL; + run->count = set->desc; + } + if (set->desc != set->count) { + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_SIMPLE; + strp = &(run->strs); + for (str = set->strs; str; str = str->next) + if (!str->desc) { + *strp = str; + strp = &(str->run); + } + *strp = NULL; + run->count = set->count - set->desc; + } + } + } else { + for (set = cd_state.sets; set; set = set->next) + if (set->count) { + *runp = run = (Cdrun) zalloc(sizeof(*run)); + runp = &(run->next); + run->type = CRT_SIMPLE; + run->strs = set->strs; + for (str = set->strs; str; str = str->next) + str->run = str->next; + run->count = set->count; + } + } + *runp = NULL; +} + +/* Duplicate and concatenate two arrays. Return the result. */ + +static char ** +cd_arrcat(char **a, char **b) +{ + if (!b) + return zarrdup(a); + else { + char **r = (char **) zalloc((arrlen(a) + arrlen(b) + 1) * + sizeof(char *)); + char **p = r; + + for (; *a; a++) + *p++ = ztrdup(*a); + for (; *b; b++) + *p++ = ztrdup(*b); + + *p = NULL; + + return r; + } } /* Initialisation. Store and calculate the string and matches and so on. */ static int -cd_init(char *nam, char *sep, char **args, int disp) +cd_init(char *nam, char *hide, char *sep, char **opts, char **args, int disp) { Cdset *setp, set; Cdstr *strp, str; @@ -195,6 +359,7 @@ cd_init(char *nam, char *sep, char **args, int disp) cd_state.slen = ztrlen(sep); cd_state.sets = NULL; cd_state.showd = disp; + cd_state.maxg = cd_state.groups = cd_state.descs = 0; if (*args && !strcmp(*args, "-g")) { args++; @@ -219,6 +384,7 @@ cd_init(char *nam, char *sep, char **args, int disp) str->kind = 0; str->other = NULL; + str->set = set; for (tmp = *ap; *tmp && *tmp != ':'; tmp++) if (*tmp == '\\' && tmp[1]) @@ -230,6 +396,7 @@ cd_init(char *nam, char *sep, char **args, int disp) str->desc = NULL; *tmp = '\0'; str->str = str->match = ztrdup(rembslash(*ap)); + str->len = strlen(str->str); } if (str) str->next = NULL; @@ -246,13 +413,23 @@ cd_init(char *nam, char *sep, char **args, int disp) args++; } + if (hide && *hide) { + for (str = set->strs; str; str = str->next) { + if (str->str == str->match) + str->str = ztrdup(str->str); + if (hide[1] && str->str[0] == '-' && str->str[1] == '-') + strcpy(str->str, str->str + 2); + else if (str->str[0] == '-' || str->str[0] == '+') + strcpy(str->str, str->str + 1); + } + } for (ap = args; *args && (args[0][0] != '-' || args[0][1] != '-' || args[0][2]); args++); tmp = *args; *args = NULL; - set->opts = zarrdup(ap); + set->opts = cd_arrcat(ap, opts); if ((*args = tmp)) args++; } @@ -260,79 +437,157 @@ cd_init(char *nam, char *sep, char **args, int disp) cd_group(); cd_calc(); + cd_prep(); cd_parsed = 1; return 0; } +/* Copy an array with one element in reserve (at the beginning). */ + +static char ** +cd_arrdup(char **a) +{ + char **r = (char **) zalloc((arrlen(a) + 2) * sizeof(char *)); + char **p = r + 1; + + while (*a) + *p++ = ztrdup(*a++); + *p = NULL; + + return r; +} + /* Get the next set. */ static int cd_get(char **params) { - Cdset set; + Cdrun run; - if ((set = cd_state.sets)) { - char **sd, **sdp, **md, **mdp, **sh, **shp, **mh, **mhp; - char **ss, **ssp, **ms, **msp; + if ((run = cd_state.runs)) { Cdstr str; - VARARR(char, buf, cd_state.pre + cd_state.suf + cd_state.slen + 1); - char *sufp = NULL, *disp; + char **mats, **mp, **dpys, **dp, **opts, *csl = ""; - 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); + cd_state.runs = run->next; + + switch (run->type) { + case CRT_SIMPLE: + mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *)); + dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *)); + + for (str = run->strs; str; str = str->run) { + *mp++ = ztrdup(str->match); + *dp++ = ztrdup(str->str ? str->str : str->match); + } + *mp = *dp = NULL; + opts = zarrdup(run->strs->set->opts); + if (cd_state.groups) { + /* We are building a columnised list with dummy matches + * but there are also matches without descriptions. + * Those end up in a different group, so make sure that + * groupd doesn't have an explanation. */ + + for (mp = dp = opts; *mp; mp++) { + if (dp[0][0] == '-' && dp[0][1] == 'X') { + if (!dp[0][2] && dp[1]) + mp++; + } else + *dp++ = *mp; } - if (strlen(disp) >= columns) - disp[columns - 1] = '\0'; + *dp = NULL; + } + break; - if (str->kind == 2) { - *shp++ = disp; - *mhp++ = ztrdup(str->match); - } else { - *sdp++ = disp; - *mdp++ = ztrdup(str->match); + case CRT_DESC: + { + VARARR(char, buf, + cd_state.pre + cd_state.suf + cd_state.slen + 1); + char *sufp = NULL; + + memcpy(buf + cd_state.pre, cd_state.sep, cd_state.slen); + sufp = buf + cd_state.pre + cd_state.slen; + + mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *)); + dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *)); + + for (str = run->strs; str; str = str->run) { + *mp++ = ztrdup(str->match); + memset(buf, ' ', cd_state.pre); + memcpy(buf, str->str, str->len); + strcpy(sufp, str->desc); + if (strlen(buf) >= columns) + buf[columns] = '\0'; + *dp++ = ztrdup(buf); } - } else { - *ssp++ = ztrdup(str->str); - *msp++ = ztrdup(str->match); + *mp = *dp = NULL; + opts = cd_arrdup(run->strs->set->opts); + opts[0] = ztrdup("-l"); + break; + } + case CRT_SPEC: + mats = (char **) zalloc(2 * sizeof(char *)); + dpys = (char **) zalloc(2 * sizeof(char *)); + mats[0] = ztrdup(run->strs->match); + dpys[0] = ztrdup(run->strs->str); + mats[1] = dpys[1] = NULL; + opts = cd_arrdup(run->strs->set->opts); + for (dp = opts + 1; *dp; dp++) + if (dp[0][0] == '-' && dp[0][1] == 'J') + break; + if (*dp) { + char *s = tricat("-1V", "", dp[0] + 2); + + zsfree(*dp); + *dp = s; + + memmove(opts, opts + 1, + (arrlen(opts + 1) + 1) * sizeof(char *)); + + } else + opts[0] = ztrdup("-1V-default-"); + csl = "packed rows"; + break; + + default: + { + int dlen = columns - cd_state.gpre - cd_state.slen; + VARARR(char, dbuf, dlen + cd_state.slen); + char buf[20]; + int i = run->type - CRT_DUMMY; + + sprintf(buf, "-E%d", i + 1); + + mats = (char **) zalloc(2 * sizeof(char *)); + dpys = (char **) zalloc((3 + i) * sizeof(char *)); + mats[0] = ztrdup(run->strs->match); + dpys[0] = ztrdup(run->strs->str); + for (dp = dpys + 1; i; i--, dp++) + *dp = ztrdup(""); + memset(dbuf + cd_state.slen, ' ', dlen - 1); + dbuf[dlen + cd_state.slen - 1] = '\0'; + strcpy(dbuf, cd_state.sep); + memcpy(dbuf + cd_state.slen, + run->strs->desc, + (strlen(run->strs->desc) >= dlen ? dlen - 1 : + strlen(run->strs->desc))); + *dp++ = ztrdup(dbuf); + mats[1] = *dp = NULL; + + opts = cd_arrdup(run->strs->set->opts); + opts[0] = ztrdup(buf); + + csl = "packed rows"; } } - *sdp = *mdp = *shp = *mhp = *ssp = *msp = NULL; - - setaparam(params[0], zarrdup(set->opts)); - setaparam(params[1], sd); - setaparam(params[2], md); - setaparam(params[3], sh); - setaparam(params[4], mh); - setaparam(params[5], ss); - setaparam(params[6], ms); + setsparam(params[0], ztrdup(csl)); + setaparam(params[1], opts); + setaparam(params[2], mats); + setaparam(params[3], dpys); - cd_state.sets = set->next; - set->next = NULL; - freecdsets(set); + zfree(run, sizeof(*run)); - return 0; + return 0; } return 1; } @@ -341,6 +596,8 @@ cd_get(char **params) static int bin_compdescribe(char *nam, char **args, char *ops, int func) { + int n = arrlen(args); + if (incompfunc != 1) { zwarnnam(nam, "can only be called from completion function", NULL, 0); return 1; @@ -351,15 +608,30 @@ bin_compdescribe(char *nam, char **args, char *ops, int func) } switch (args[0][1]) { case 'i': - return cd_init(nam, "", args + 1, 0); + if (n < 2) { + zwarnnam(nam, "not enough arguments", NULL, 0); + + return 1; + } + return cd_init(nam, args[1], "", NULL, args + 2, 0); case 'I': - return cd_init(nam, args[1], args + 2, 1); + if (n < 5) { + zwarnnam(nam, "not enough arguments", NULL, 0); + + return 1; + } else { + char **opts; + + if (!(opts = getaparam(args[3]))) { + zwarnnam(nam, "unknown parameter: %s", args[2], 0); + return 1; + } + return cd_init(nam, args[1], args[2], opts, args + 4, 1); + } case 'g': if (cd_parsed) { - int n = arrlen(args); - - if (n != 8) { - zwarnnam(nam, (n < 8 ? "not enough arguments" : + if (n != 5) { + zwarnnam(nam, (n < 5 ? "not enough arguments" : "too many arguments"), NULL, 0); return 1; } |