diff options
Diffstat (limited to 'Src/Zle/compcore.c')
-rw-r--r-- | Src/Zle/compcore.c | 154 |
1 files changed, 95 insertions, 59 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 131e86825..09282d42d 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1187,9 +1187,9 @@ check_param(char *s, int set, int test) return NULL; /* Ignore the possible (...) flags. */ - tb = ++b, br++; - if ((qstring ? skipparens('(', ')', &tb) : - skipparens(Inpar, Outpar, &tb)) > 0 || tb - s >= offs) { + b++, br++; + if ((qstring ? skipparens('(', ')', &b) : + skipparens(Inpar, Outpar, &b)) > 0 || b - s > offs) { /* * We are still within the parameter flags. There's no * point trying to do anything clever here with @@ -1200,14 +1200,6 @@ check_param(char *s, int set, int test) ispar = 2; return NULL; } - if ((qstring ? '(' : Inpar) == *b) { - /* - * We are inside the braces but on the opening paren. - * There is nothing useful to complete here? - */ - return NULL; - } else - b = tb; /* Skip over the flags */ for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--); if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring)) @@ -1238,14 +1230,14 @@ check_param(char *s, int set, int test) else if (idigit(*e)) while (idigit(*e)) e++; - else if ((ie = itype_end(e, IIDENT, 0)) != e) { + else if ((ie = itype_end(e, INAMESPC, 0)) != e) { do { e = ie; if (comppatmatch && *comppatmatch && (*e == Star || *e == Quest)) ie = e + 1; else - ie = itype_end(e, IIDENT, 0); + ie = itype_end(e, INAMESPC, 0); } while (ie != e); } @@ -2081,10 +2073,10 @@ addmatches(Cadata dat, char **argv) /* ms: "match string" - string to use as completion. * Overloaded at one place as a temporary. */ char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre; + char **aign = NULL, ***dparr = NULL, *oaq = autoq, *oppre = dat->ppre; char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL; char **arrays = NULL; - int lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; + int dind, lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; int ppl = 0, psl = 0, ilen = 0; int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern; int isexact, doadd, ois = instring, oib = inbackt; @@ -2092,7 +2084,7 @@ addmatches(Cadata dat, char **argv) struct cmlist mst; Cmlist oms = mstack; Patprog cp = NULL, *pign = NULL; - LinkList aparl = NULL, oparl = NULL, dparl = NULL; + LinkList aparl = NULL, oparl = NULL, *dparl = NULL; Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; Heap oldheap; @@ -2120,7 +2112,7 @@ addmatches(Cadata dat, char **argv) curexpl->always = !!dat->mesg; curexpl->count = curexpl->fcount = 0; curexpl->str = dupstring(dat->mesg ? dat->mesg : dat->exp); - if (dat->mesg) + if (dat->mesg && !dat->dpar && !dat->opar && !dat->apar) addexpl(1); } else curexpl = NULL; @@ -2186,11 +2178,24 @@ addmatches(Cadata dat, char **argv) if (dat->opar) oparl = newlinklist(); if (dat->dpar) { - if (*(dat->dpar) == '(') - dparr = NULL; - else if ((dparr = get_user_var(dat->dpar)) && !*dparr) - dparr = NULL; - dparl = newlinklist(); + int darr = 0, dparlen = arrlen(dat->dpar); + char **tail = dat->dpar + dparlen; + + dparr = (char ***)hcalloc((1 + dparlen) * sizeof(char **)); + dparl = (LinkList *)hcalloc((1 + dparlen) * sizeof(LinkList)); + queue_signals(); + while (darr < dparlen) { + if ((dparr[darr] = getaparam(dat->dpar[darr])) && *dparr[darr]) { + dparr[darr] = arrdup(dparr[darr]); + dparl[darr++] = newlinklist(); + } else { + /* swap in the last -D argument if we didn't get a non-empty array */ + dat->dpar[darr] = *--tail; + *tail = NULL; + --dparlen; + } + } + unqueue_signals(); } /* Store the matcher in our stack of matchers. */ if (dat->match) { @@ -2244,8 +2249,9 @@ addmatches(Cadata dat, char **argv) llpl = strlen(lpre); llsl = strlen(lsuf); - if (llpl + (int)strlen(compqiprefix) + (int)strlen(lipre) != origlpre - || llsl + (int)strlen(compqisuffix) + (int)strlen(lisuf) != origlsuf) + /* This used to reference compqiprefix and compqisuffix, why? */ + if (llpl + (int)strlen(qipre) + (int)strlen(lipre) != origlpre + || llsl + (int)strlen(qisuf) + (int)strlen(lisuf) != origlsuf) lenchanged = 1; /* Test if there is an existing -P prefix. */ @@ -2507,8 +2513,10 @@ addmatches(Cadata dat, char **argv) } if (!addit) { compignored++; - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } } @@ -2525,8 +2533,10 @@ addmatches(Cadata dat, char **argv) !(dat->flags & CMF_FILE) ? 1 : 2) : 0), &bpl, bcp, &bsl, bcs, &isexact))) { - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } if (doadd) { @@ -2553,10 +2563,14 @@ addmatches(Cadata dat, char **argv) addlinknode(aparl, ms); if (dat->opar) addlinknode(oparl, s); - if (dat->dpar && dparr) { - addlinknode(dparl, *dparr); - if (!*++dparr) - dparr = NULL; + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) { + if (dparr[dind]) { + addlinknode(dparl[dind], *dparr[dind]); + if (!*++dparr[dind]) + dparr[dind] = NULL; + } + } } free_cline(lc); } @@ -2584,8 +2598,10 @@ addmatches(Cadata dat, char **argv) set_list_array(dat->apar, aparl); if (dat->opar) set_list_array(dat->opar, oparl); - if (dat->dpar) - set_list_array(dat->dpar, dparl); + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) + set_list_array(dat->dpar[dind], dparl[dind]); + } if (dat->exp) addexpl(0); if (!hasallmatch && (dat->aflags & CAF_ALL)) { @@ -2883,9 +2899,9 @@ add_match_data(int alt, char *str, char *orig, Cline line, *t++ = '$'; *t++ = '\''; *t++ = '\\'; - *t++ = '0' + ((STOUC(curchar) >> 6) & 7); - *t++ = '0' + ((STOUC(curchar) >> 3) & 7); - *t++ = '0' + (STOUC(curchar) & 7); + *t++ = '0' + (((unsigned char) curchar >> 6) & 7); + *t++ = '0' + (((unsigned char) curchar >> 3) & 7); + *t++ = '0' + ((unsigned char) curchar & 7); *t++ = '\''; } while (cnt == MB_INCOMPLETE && fs < fe); /* Scanning restarts from the spot after the char we skipped. */ @@ -3232,17 +3248,20 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) } *cp = NULL; } - } else { + } else if (n > 0) { if (!(flags & CGF_NOSORT)) { /* Now sort the array (it contains matches). */ matchorder = flags; qsort((void *) rp, n, sizeof(Cmatch), - (int (*) _((const void *, const void *)))matchcmp); + (int (*) (const void *, const void *))matchcmp); + /* since the matches are sorted and the default is to remove + * all duplicates, -1 (remove only consecutive dupes) is a no-op, + * so this condition only checks for -2 */ if (!(flags & CGF_UNIQCON)) { int dup; - /* And delete the ones that occur more than once. */ + /* we did not pass -2 so go ahead and remove those dupes */ for (ap = cp = rp; *ap; ap++) { *cp++ = *ap; for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--); @@ -3264,30 +3283,47 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) if ((*ap)->flags & (CMF_NOLIST | CMF_MULT)) nl++; } + /* used -O nosort or -V, don't sort */ } else { + /* didn't use -1 or -2, so remove all duplicates (efficient) */ if (!(flags & CGF_UNIQALL) && !(flags & CGF_UNIQCON)) { - int dup; - - for (ap = rp; *ap; ap++) { - for (bp = cp = ap + 1; *bp; bp++) { - if (!matcheq(*ap, *bp)) - *cp++ = *bp; - else + int dup, del = 0; + + /* To avoid O(n^2) here, sort a copy of the list, then remove marked elements */ + matchorder = flags; + Cmatch *sp, *asp; + sp = (Cmatch *) zhalloc((n + 1) * sizeof(Cmatch)); + memcpy(sp, rp, (n + 1) * sizeof(Cmatch)); + qsort((void *) sp, n, sizeof(Cmatch), + (int (*) (const void *, const void *))matchcmp); + for (asp = sp + 1; *asp; asp++) { + Cmatch *ap = asp - 1, *bp = asp; + if (matcheq(*ap, *bp)) { + bp[0]->flags = CMF_DELETE; + del = 1; + } else if (!ap[0]->disp) { + /* Mark those, that would show the same string in the list. */ + for (dup = 0; bp[0] && !(bp[0])->disp && + !strcmp((*ap)->str, (bp[0])->str); bp = ++sp) { + (bp[0])->flags |= CMF_MULT; + dup = 1; + } + if (dup) + (*ap)->flags |= CMF_FMULT; + } + } + if (del) { + int n_orig = n; + for (bp = rp, ap = rp; bp < rp + n_orig; ap++, bp++) { + while (bp < rp + n_orig && (bp[0]->flags & CMF_DELETE)) { + bp++; n--; + } + *ap = *bp; } - *cp = NULL; - if (!(*ap)->disp) { - for (dup = 0, bp = ap + 1; *bp; bp++) - if (!(*bp)->disp && - !((*bp)->flags & CMF_MULT) && - !strcmp((*ap)->str, (*bp)->str)) { - (*bp)->flags |= CMF_MULT; - dup = 1; - } - if (dup) - (*ap)->flags |= CMF_FMULT; - } + *ap = NULL; } + /* passed -1 but not -2, so remove consecutive duplicates (efficient) */ } else if (!(flags & CGF_UNIQCON)) { int dup; |