diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 3 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 43 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 128 |
3 files changed, 93 insertions, 81 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index b0fbf3ac6..ab8d62c8a 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -227,7 +227,8 @@ struct cmatch { #define CMF_FILE 1 /* this is a file */ #define CMF_REMOVE 2 /* remove the suffix */ #define CMF_PARBR 4 /* paramter expansion with a brace */ -#define CMF_NOLIST 8 /* should not be listed */ +#define CMF_PARNEST 8 /* nested paramter expansion */ +#define CMF_NOLIST 16 /* should not be listed */ /* Stuff for completion matcher control. */ diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index e9ff83387..31daff24c 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1947,25 +1947,25 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) if (compcurrent - 1 < na || compcurrent - 1 > nb) return 0; - - restrict_range(na, nb); + if (mod) + restrict_range(na, nb); return 1; } case CVT_RANGEPAT: { char **p; int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1; - Comp c; + Patprog pp; i = compcurrent - 1; if (i < 0 || i >= l) return 0; singsub(&sa); - c = parsereg(sa); + pp = patcompile(sa, PAT_STATIC, NULL); for (i--, p = compwords + i; i >= 0; p--, i--) { - if (domatch(*p, c, 0)) { + if (pattry(pp, *p)) { b = i + 1; t = 1; break; @@ -1975,10 +1975,10 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) int tt = 0; singsub(&sb); - c = parsereg(sb); + pp = patcompile(sb, PAT_STATIC, NULL); for (i++, p = compwords + i; i < l; p++, i++) { - if (domatch(*p, c, 0)) { + if (pattry(pp, *p)) { e = i - 1; tt = 1; break; @@ -1989,7 +1989,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) } if (e < b) t = 0; - if (t) + if (t && mod) restrict_range(b, e); return t; } @@ -2011,12 +2011,12 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) case CVT_PREPAT: case CVT_SUFPAT: { - Comp c; + Patprog pp; if (!na) return 0; - if (!(c = parsereg(sa))) + if (!(pp = patcompile(sa, PAT_STATIC, 0))) return 0; if (test == CVT_PREPAT) { @@ -2036,15 +2036,15 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) for (; l; l--, p += add) { sav = *p; *p = '\0'; - test = domatch(compprefix, c, 0); + test = pattry(pp, compprefix); *p = sav; if (test && !--na) break; } if (!l) return 0; - - ignore_prefix(p - compprefix); + if (mod) + ignore_prefix(p - compprefix); } else { int l, ol, add; char *p; @@ -2060,13 +2060,13 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) add = -1; } for (; l; l--, p += add) - if (domatch(p, c, 0) && !--na) + if (pattry(pp, p) && !--na) break; if (!l) return 0; - - ignore_suffix(ol - (p - compsuffix)); + if (mod) + ignore_suffix(ol - (p - compsuffix)); } return 1; } @@ -2126,9 +2126,11 @@ bin_compset(char *name, char **argv, char *ops, int func) case CVT_RANGEPAT: tokenize(sa); sa = rembslash(sa); + remnulargs(sa); if (sb) { tokenize(sb); sb = rembslash(sb); + remnulargs(sb); } break; case CVT_PRENUM: @@ -2144,6 +2146,7 @@ bin_compset(char *name, char **argv, char *ops, int func) na = -1; tokenize(sa); sa = rembslash(sa); + remnulargs(sa); break; } return !do_comp_vars(test, na, sa, nb, sb, 1); @@ -2469,10 +2472,10 @@ cond_psfix(char **a, int id) { if (comp_check()) { if (a[1]) - return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1), + return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1, 1), 0, NULL, 0); else - return do_comp_vars(id, -1, cond_str(a, 0), 0, NULL, 0); + return do_comp_vars(id, -1, cond_str(a, 0, 1), 0, NULL, 0); } return 0; } @@ -2481,8 +2484,8 @@ cond_psfix(char **a, int id) static int cond_range(char **a, int id) { - return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0), 0, - (id ? cond_str(a, 1) : NULL), 0); + return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0, 1), 0, + (id ? cond_str(a, 1, 1) : NULL), 0); } static struct builtin bintab[] = { diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 9f4fa0c93..347eb9ffa 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -163,7 +163,7 @@ static int ispattern, haspattern; * from the whole word we are completing and the second one from that * * part of the word that was identified as a possible filename. */ -static Comp patcomp, filecomp; +static Patprog patcomp, filecomp; /* We store the following prefixes/suffixes: * * lpre/lsuf -- what's on the line * @@ -728,7 +728,7 @@ check_param(char *s, int set, int test) if ((*p == String || *p == Qstring) && p[1] != Inpar && p[1] != Inbrack) { /* This is really a parameter expression (not $(...) or $[...]). */ char *b = p + 1, *e = b; - int n = 0, br = 1; + int n = 0, br = 1, nest = 0; if (*b == Inbrace) { char *tb = b; @@ -740,6 +740,10 @@ check_param(char *s, int set, int test) /* Ignore the possible (...) flags. */ b++, br++; n = skipparens(Inpar, Outpar, &b); + + for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--); + if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring)) + nest = 1; } /* Ignore the stuff before the parameter name. */ @@ -788,9 +792,11 @@ check_param(char *s, int set, int test) * global variables. */ if (set) { - if (br >= 2) + if (br >= 2) { mflags |= CMF_PARBR; - + if (nest) + mflags |= CMF_PARNEST; + } /* Get the prefix (anything up to the character before the name). */ isuf = dupstring(e); untokenize(isuf); @@ -2542,9 +2548,12 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test) lm = NULL; } else { /* No matcher and different characters: l does not match w. */ + if (test) + return 0; + abort_match(); - return (test ? 0 : -1); + return -1; } } /* If this is a recursive call, we just return if l matched w or not. */ @@ -2600,7 +2609,7 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test) * and the suffix don't match the word w. */ static char * -comp_match(char *pfx, char *sfx, char *w, Comp cp, +comp_match(char *pfx, char *sfx, char *w, Patprog cp, Cline *clp, int qu, int *bpl, int *bsl, int *exact) { char *r = NULL; @@ -2610,7 +2619,7 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp, int wl; r = w; - if (!domatch(r, cp, 0)) + if (!pattry(cp, r)) return NULL; r = (qu ? quotename(r, NULL) : dupstring(r)); @@ -2868,7 +2877,8 @@ join_strs(int la, char *sa, int lb, char *sb) *ap += mp->wlen; *alp -= mp->wlen; *bp += bl; *blp -= bl; t = 1; - } + } else + t = 0; } } } @@ -2907,7 +2917,7 @@ cmp_anchors(Cline o, Cline n, int join) /* First try the exact strings. */ if ((!(o->flags & CLF_LINE) && o->wlen == n->wlen && (!o->word || !strncmp(o->word, n->word, o->wlen))) || - (line = ((!o->line && !n->line) || + (line = ((!o->line && !n->line && !o->wlen && !n->wlen) || (o->llen == n->llen && o->line && n->line && !strncmp(o->line, n->line, o->llen))))) { if (line) { @@ -3419,6 +3429,11 @@ join_clines(Cline o, Cline n) } /* Now see if they have matching anchors. If not, cut the list. */ if (!(o->flags & CLF_MID) && !cmp_anchors(o, n, 1)) { +#if 0 + /* This used to search forward for matching anchors. + * Unfortunately this does the wrong thing if the prefixes + * before the differing anchors match nicely. */ + Cline t, tn; for (t = n; (tn = t->next) && !cmp_anchors(o, tn, 1); t = tn); @@ -3427,6 +3442,7 @@ join_clines(Cline o, Cline n) n = tn; continue; } else { +#endif if (o->flags & CLF_SUF) break; @@ -3434,7 +3450,10 @@ join_clines(Cline o, Cline n) o->wlen = 0; free_cline(o->next); o->next = NULL; + o->flags |= CLF_MISS; +#if 0 } +#endif } /* Ok, they are equal, now join the sub-lists. */ if (o->flags & CLF_MID) @@ -3726,7 +3745,7 @@ int addmatches(Cadata dat, char **argv) { char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL, **dparr = NULL, oaq = autoq; + char **aign = NULL, **dparr = NULL, oaq = autoq, *oppre = dat->ppre; char *oqp = qipre, *oqs = qisuf, qc; int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum; int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt; @@ -3734,7 +3753,7 @@ addmatches(Cadata dat, char **argv) Cmatch cm; struct cmlist mst; Cmlist oms = mstack; - Comp cp = NULL; + Patprog cp = NULL; LinkList aparl = NULL, oparl = NULL, dparl = NULL; if (compquote && (qc = *compquote)) { @@ -3798,13 +3817,8 @@ addmatches(Cadata dat, char **argv) /* Get the contents of the completion variables if we have * to perform matching. */ if (dat->aflags & CAF_MATCH) { - if (dat->aflags & CAF_QUOTE) { - lipre = dupstring(compiprefix); - lisuf = dupstring(compisuffix); - } else { - lipre = quotename(compiprefix, NULL); - lisuf = quotename(compisuffix, NULL); - } + lipre = dupstring(compiprefix); + lisuf = dupstring(compisuffix); lpre = dupstring(compprefix); lsuf = dupstring(compsuffix); llpl = strlen(lpre); @@ -3830,7 +3844,7 @@ addmatches(Cadata dat, char **argv) if (haswilds(tmp)) { if (is) tmp[llpl] = Star; - if ((cp = parsereg(tmp))) + if ((cp = patcompile(tmp, 0, NULL))) haspattern = 1; } } @@ -3847,12 +3861,21 @@ addmatches(Cadata dat, char **argv) else if (lisuf) dat->isuf = lisuf; if (dat->ppre) { - dat->ppre = dupstring(dat->ppre); + if (!(dat->aflags & CAF_QUOTE)) { + dat->ppre = quotename(dat->ppre, NULL); + if ((dat->flags & CMF_FILE) && + dat->ppre[0] == '\\' && dat->ppre[1] == '~') + chuck(dat->ppre); + } else + dat->ppre = dupstring(dat->ppre); lpl = strlen(dat->ppre); } else lpl = 0; if (dat->psuf) { - dat->psuf = dupstring(dat->psuf); + if (!(dat->aflags & CAF_QUOTE)) + dat->psuf = quotename(dat->psuf, NULL); + else + dat->psuf = dupstring(dat->psuf); lsl = strlen(dat->psuf); } else lsl = 0; @@ -3877,7 +3900,7 @@ addmatches(Cadata dat, char **argv) dat->pre = dupstring(dat->pre); if (dat->suf) dat->suf = dupstring(dat->suf); - if (!dat->prpre && (dat->prpre = dat->ppre)) { + if (!dat->prpre && (dat->prpre = oppre)) { singsub(&(dat->prpre)); untokenize(dat->prpre); } else @@ -3901,22 +3924,6 @@ addmatches(Cadata dat, char **argv) dat->rems = NULL; } else if (dat->rems) dat->rems = dupstring(dat->rems); - - /* Probably quote the prefix and suffix for testing. */ - if (!(dat->aflags & CAF_QUOTE)) { - if (!cp && (dat->aflags & CAF_MATCH)) { - lpre = quotename(lpre, NULL); - lsuf = quotename(lsuf, NULL); - } - if (dat->ppre) { - dat->ppre = quotename(dat->ppre, NULL); - if ((dat->flags & CMF_FILE) && - dat->ppre[0] == '\\' && dat->ppre[1] == '~') - chuck(dat->ppre); - } - if (dat->psuf) - dat->psuf = quotename(dat->psuf, NULL); - } } /* Walk through the matches given. */ for (; (s = *argv); argv++) { @@ -4340,7 +4347,7 @@ gen_matches_files(int dirs, int execs, int all) addwhat = execs ? -8 : -5; if (filecomp) /* If we have a pattern for the filename check, use it. */ - test = domatch(n, filecomp, 0); + test = pattry(filecomp, n); else { /* Otherwise use the prefix and suffix strings directly. */ e = n + strlen(n) - fsl; @@ -5024,8 +5031,6 @@ comp_str(int *ipl, int *pl, int untok) remnulargs(p); ctokenize(s); remnulargs(s); - ctokenize(ip); - remnulargs(ip); } lp = strlen(p); ls = strlen(s); @@ -5563,14 +5568,14 @@ static int makecomplistpc(char *os, int incmd) { Patcomp pc; - Comp pat; + Patprog pat; char *s = findcmd(cmdstr, 1); int ret = 0; for (pc = patcomps; pc; pc = pc->next) { - if ((pat = parsereg(pc->pat)) && - (domatch(cmdstr, pat, 0) || - (s && domatch(s, pat, 0)))) { + if ((pat = patcompile(pc->pat, PAT_STATIC, NULL)) && + (pattry(pat, cmdstr) || + (s && pattry(pat, s)))) { makecomplistcc(pc->cc, os, incmd); ret |= 2; if (!(ccont & CC_CCCONT)) @@ -5666,7 +5671,7 @@ makecomplistext(Compctl occ, char *os, int incmd) { Compctl compc; Compcond or, cc; - Comp comp; + Patprog pprog; int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins; char *sc = NULL, *s, *ss; @@ -5752,8 +5757,8 @@ makecomplistext(Compctl occ, char *os, int incmd) if (cc->type == CCT_CURPAT || cc->type == CCT_WORDPAT) { tokenize(ss = dupstring(cc->u.s.s[i])); - t = ((comp = parsereg(ss)) && - domatch(s, comp, 0)); + t = ((pprog = patcompile(ss, PAT_STATIC, NULL)) && + pattry(pprog, s)); } else t = (!strcmp(s, rembslash(cc->u.s.s[i]))); break; @@ -5767,8 +5772,8 @@ makecomplistext(Compctl occ, char *os, int incmd) sc = rembslash(cc->u.l.a[i]); if (cc->type == CCT_RANGESTR ? !strncmp(s, sc, strlen(sc)) : - ((comp = parsereg(sc)) && - domatch(s, comp, 0))) { + ((pprog = patcompile(sc, PAT_STATIC, 0)) && + pattry(pprog, s))) { zsfree(s); brange = j + 1; t = 1; @@ -5785,8 +5790,8 @@ makecomplistext(Compctl occ, char *os, int incmd) sc = rembslash(cc->u.l.b[i]); if (cc->type == CCT_RANGESTR ? !strncmp(s, sc, strlen(sc)) : - ((comp = parsereg(sc)) && - domatch(s, comp, 0))) { + ((pprog = patcompile(sc, PAT_STATIC, 0)) && + pattry(pprog, s))) { zsfree(s); erange = j - 1; t = clwpos <= erange; @@ -6050,7 +6055,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) strcpy(p + rpl + 1, rsuf); } else strcpy(p + rpl, rsuf); - patcomp = parsereg(p); + patcomp = patcompile(p, 0, NULL); haspattern = 1; } if (!patcomp) { @@ -6148,7 +6153,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) (!comppatmatch || *comppatmatch == '*')) p[t2++] = Star; strcpy(p + t2, fsuf); - filecomp = parsereg(p); + filecomp = patcompile(p, 0, NULL); } if (!filecomp) { untokenize(fpre); @@ -6567,7 +6572,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) } if (cc->hpat) { /* We have a pattern to take things from the history. */ - Comp compc = NULL; + Patprog pprogc = NULL; char *e, *h, hpatsav; Histent he; int i = addhistnum(curhist,-1,HIST_FOREIGN), n = cc->hnum; @@ -6577,7 +6582,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) char *thpat = dupstring(cc->hpat); tokenize(thpat); - compc = parsereg(thpat); + pprogc = patcompile(thpat, 0, NULL); } /* n holds the number of history line we have to search. */ if (!n) @@ -6594,7 +6599,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) /* We now have a word from the history, ignore it * * if it begins with a quote or `$'. */ if (*h != '\'' && *h != '"' && *h != '`' && *h != '$' && - (!compc || domatch(h, compc, 0))) + (!pprogc || pattry(pprogc, h))) /* Otherwise add it if it was matched. */ addmatch(dupstring(h), NULL); if (hpatsav) @@ -7729,6 +7734,8 @@ do_single(Cmatch m) minfo.insc++; if (minfo.we) minfo.end += minfo.insc; + if (m->flags & CMF_PARNEST) + havesuff = 1; } if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) { /* If we have a filename or we completed a parameter name * @@ -7742,11 +7749,12 @@ do_single(Cmatch m) t = 1; else { /* Build the path name. */ - if (m->ripre && !*psuf) { + if (m->ripre && !*psuf && !(m->flags & CMF_PARNEST)) { int ne = noerrs; - p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 1); - sprintf(p, "%s%s", m->ripre, str); + p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 2); + sprintf(p, "%s%s%c", m->ripre, str, + ((m->flags & CMF_PARBR) ? Outbrace : '\0')); noerrs = 1; parsestr(p); singsub(&p); |