diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2005-03-21 18:58:28 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2005-03-21 18:58:28 +0000 |
commit | 2a59e22f73bb2ba0a96daf0e84b6da4fe48c1280 (patch) | |
tree | 956194a7343220bcf692c6a15efc81aeaeb177ac /Src/Zle/compcore.c | |
parent | e222689ea14bcf037ef5085d85216c8bd2ddd3d0 (diff) | |
download | zsh-2a59e22f73bb2ba0a96daf0e84b6da4fe48c1280.tar.gz zsh-2a59e22f73bb2ba0a96daf0e84b6da4fe48c1280.tar.xz zsh-2a59e22f73bb2ba0a96daf0e84b6da4fe48c1280.zip |
21045: fix some uses of Meta characters in completion
Diffstat (limited to 'Src/Zle/compcore.c')
-rw-r--r-- | Src/Zle/compcore.c | 840 |
1 files changed, 606 insertions, 234 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 48189ab31..084895ae1 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -39,16 +39,23 @@ static Widget lastcompwidget; /**/ int useexact, useline, uselist, forcelist, startauto; +/**/ +mod_export int iforcemenu; + /* Non-zero if we should go back to the last prompt. */ /**/ -int dolastprompt; +mod_export int dolastprompt; /* Non-zero if we should keep an old list. */ /**/ -mod_export -int oldlist, oldins; +mod_export int oldlist, oldins; + +/* Original prefix/suffix lengths. Flag saying if they changed. */ + +/**/ +int origlpre, origlsuf, lenchanged; /* This is used to decide when the cursor should be moved to the end of * * the inserted word: 0 - never, 1 - only when a single match is inserted, * @@ -60,7 +67,12 @@ int movetoend; /* The match and group number to insert when starting menucompletion. */ /**/ -mod_export int insmnum, insgnum, insgroup, insspace; +mod_export int insmnum, insspace; + +#if 0 +/* group-numbers in compstate[insert] */ +int insgnum, insgroup; /* mod_export */ +#endif /* Information about menucompletion. */ @@ -131,6 +143,11 @@ mod_export Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches; /**/ mod_export int hasoldlist, hasperm; +/* Non-zero if we have a match representing all other matches. */ + +/**/ +int hasallmatch; + /* Non-zero if we have newly added matches. */ /**/ @@ -148,6 +165,16 @@ mod_export int nmatches; /**/ mod_export int smatches; +/* != 0 if more than one match and at least two different matches */ + +/**/ +mod_export int diffmatches; + +/* The number of messages. */ + +/**/ +mod_export int nmessages; + /* != 0 if only explanation strings should be printed */ /**/ @@ -250,7 +277,7 @@ int fromcomp; /* This holds the end-position of the last string inserted into the line. */ /**/ -int lastend; +mod_export int lastend; #define inststr(X) inststrlen((X),1,-1) @@ -258,9 +285,9 @@ int lastend; /**/ int -do_completion(Hookdef dummy, Compldat dat) +do_completion(UNUSED(Hookdef dummy), Compldat dat) { - int ret = 0, lst = dat->lst, incmd = dat->incmd; + int ret = 0, lst = dat->lst, incmd = dat->incmd, osl = showinglist; char *s = dat->s; char *opm; LinkNode n; @@ -278,7 +305,7 @@ do_completion(Hookdef dummy, Compldat dat) compqstack[0] = '\''; hasunqu = 0; - useline = (lst != COMP_LIST_COMPLETE); + useline = (wouldinstab ? -1 : (lst != COMP_LIST_COMPLETE)); useexact = isset(RECEXACT); zsfree(compexactstr); compexactstr = ztrdup(""); @@ -307,6 +334,9 @@ do_completion(Hookdef dummy, Compldat dat) hasmatched = hasunmatched = 0; minmlen = 1000000; maxmlen = -1; + compignored = 0; + nmessages = 0; + hasallmatch = 0; /* Make sure we have the completion list and compctl. */ if (makecomplist(s, incmd, lst)) { @@ -318,6 +348,8 @@ do_completion(Hookdef dummy, Compldat dat) clearlist = 1; ret = 1; minfo.cur = NULL; + if (useline < 0) + ret = selfinsert(zlenoargs); goto compend; } zsfree(lastprebr); @@ -326,7 +358,13 @@ do_completion(Hookdef dummy, Compldat dat) if (comppatmatch && *comppatmatch && comppatmatch != opm) haspattern = 1; - if (!useline && uselist) { + if (iforcemenu) { + if (nmatches) + do_ambig_menu(); + ret = !nmatches; + } else if (useline < 0) + ret = selfinsert(zlenoargs); + else if (!useline && uselist) { /* All this and the guy only wants to see the list, sigh. */ cs = 0; foredel(ll); @@ -334,41 +372,8 @@ do_completion(Hookdef dummy, Compldat dat) cs = origcs; showinglist = -2; } else if (useline == 2 && nmatches > 1) { - int first = 1, nm = nmatches; - Cmatch *mc; - - menucmp = 1; - menuacc = 0; - - for (minfo.group = amatches; - minfo.group && !(minfo.group)->mcount; - minfo.group = (minfo.group)->next); + do_allmatches(1); - mc = (minfo.group)->matches; - - while (1) { - if (!first) - accept_last(); - first = 0; - - if (!--nm) - menucmp = 0; - - do_single(*mc); - minfo.cur = mc; - - if (!*++(minfo.cur)) { - do { - if (!(minfo.group = (minfo.group)->next)) - break; - } while (!(minfo.group)->mcount); - if (!minfo.group) - break; - minfo.cur = minfo.group->matches; - } - mc = minfo.cur; - } - menucmp = 0; minfo.cur = NULL; if (forcelist) @@ -377,10 +382,13 @@ do_completion(Hookdef dummy, Compldat dat) invalidatelist(); } else if (useline) { /* We have matches. */ - if (nmatches > 1) { + if (nmatches > 1 && diffmatches) { /* There is more than one match. */ ret = do_ambiguous(); - } else if (nmatches == 1) { + + if (!showinglist && uselist && listshown && (usemenu == 2 || oldlist)) + showinglist = osl; + } else if (nmatches == 1 || (nmatches > 1 && !diffmatches)) { /* Only one match. */ Cmgroup m = amatches; @@ -396,6 +404,11 @@ do_completion(Hookdef dummy, Compldat dat) clearlist = 1; } else invalidatelist(); + } else if (nmessages && forcelist) { + if (uselist) + showinglist = -2; + else + clearlist = 1; } } else { invalidatelist(); @@ -407,9 +420,10 @@ do_completion(Hookdef dummy, Compldat dat) cs = origcs; } /* Print the explanation strings if needed. */ - if (!showinglist && validlist && usemenu != 2 && nmatches != 1 && - useline != 2 && (!oldlist || !listshown)) { - onlyexpl = 1; + if (!showinglist && validlist && usemenu != 2 && uselist && + (nmatches != 1 || diffmatches) && + useline >= 0 && useline != 2 && (!oldlist || !listshown)) { + onlyexpl = 3; showinglist = -2; } compend: @@ -430,7 +444,7 @@ static int oldmenucmp; /**/ int -before_complete(Hookdef dummy, int *lst) +before_complete(UNUSED(Hookdef dummy), int *lst) { oldmenucmp = menucmp; @@ -469,22 +483,40 @@ before_complete(Hookdef dummy, int *lst) /**/ int -after_complete(Hookdef dummy, Compldat dat) +after_complete(UNUSED(Hookdef dummy), int *dat) { if (menucmp && !oldmenucmp) { - struct chdata dat; - - dat.matches = amatches; - dat.num = nmatches; - dat.cur = NULL; - if (runhookdef(MENUSTARTHOOK, (void *) &dat)) + struct chdata cdat; + int ret; + + cdat.matches = amatches; + cdat.num = nmatches; + cdat.nmesg = nmessages; + cdat.cur = NULL; + if ((ret = runhookdef(MENUSTARTHOOK, (void *) &cdat))) { + dat[1] = 0; menucmp = menuacc = 0; + minfo.cur = NULL; + if (ret >= 2) { + fixsuffix(); + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + if (ret == 2) { + clearlist = 1; + invalidatelist(); + } + } + } } return 0; } /* This calls the given completion widget function. */ +static int parwb, parwe, paroffs; + /**/ static void callcompfunc(char *s, char *fn) @@ -521,6 +553,8 @@ callcompfunc(char *s, char *fn) compparameter = compredirect = ""; if (ispar) compcontext = (ispar == 2 ? "brace_parameter" : "parameter"); + else if (linwhat == IN_PAR) + compcontext = "assign_parameter"; else if (linwhat == IN_MATH) { if (insubscr) { compcontext = "subscript"; @@ -584,7 +618,14 @@ callcompfunc(char *s, char *fn) untokenize(*q = ztrdup(*p)); *q = NULL; } else - compwords = (char **) zcalloc(sizeof(char *)); + compwords = (char **) zshcalloc(sizeof(char *)); + + if (compredirs) + freearray(compredirs); + if (rdstrs) + compredirs = bld_list_array(rdstrs); + else + compredirs = (char **) zshcalloc(sizeof(char *)); compparameter = ztrdup(compparameter); compredirect = ztrdup(compredirect); @@ -610,7 +651,7 @@ callcompfunc(char *s, char *fn) zsfree(compprefix); zsfree(compsuffix); if (unset(COMPLETEINWORD)) { - tmp = multiquote(s, 0); + tmp = (linwhat == IN_MATH ? dupstring(s) : multiquote(s, 0)); untokenize(tmp); compprefix = ztrdup(tmp); compsuffix = ztrdup(""); @@ -621,22 +662,46 @@ callcompfunc(char *s, char *fn) sav = *ss; *ss = '\0'; - tmp = multiquote(s, 0); + tmp = (linwhat == IN_MATH ? dupstring(s) : multiquote(s, 0)); untokenize(tmp); compprefix = ztrdup(tmp); *ss = sav; - ss = multiquote(ss, 0); + ss = (linwhat == IN_MATH ? dupstring(ss) : multiquote(ss, 0)); untokenize(ss); compsuffix = ztrdup(ss); } + zsfree(complastprefix); + zsfree(complastsuffix); + complastprefix = ztrdup(compprefix); + complastsuffix = ztrdup(compsuffix); zsfree(compiprefix); - compiprefix = ztrdup(""); zsfree(compisuffix); - compisuffix = ztrdup(""); + if (parwb < 0) { + compiprefix = ztrdup(""); + compisuffix = ztrdup(""); + } else { + int l; + + compiprefix = (char *) zalloc((l = wb - parwb) + 1); + memcpy(compiprefix, line + parwb, l); + compiprefix[l] = '\0'; + compisuffix = (char *) zalloc((l = parwe - we) + 1); + memcpy(compisuffix, line + we, l); + compisuffix[l] = '\0'; + + wb = parwb; + we = parwe; + offs = paroffs; + } zsfree(compqiprefix); compqiprefix = ztrdup(qipre ? qipre : ""); zsfree(compqisuffix); compqisuffix = ztrdup(qisuf ? qisuf : ""); + origlpre = (strlen(compqiprefix) + strlen(compiprefix) + + strlen(compprefix)); + origlsuf = (strlen(compqisuffix) + strlen(compisuffix) + + strlen(compsuffix)); + lenchanged = 0; compcurrent = (usea ? (clwpos + 1 - aadd) : 0); zsfree(complist); @@ -667,7 +732,9 @@ callcompfunc(char *s, char *fn) compinsert = ""; kset &= ~CP_INSERT; } - compinsert = ztrdup(compinsert); + compinsert = (useline < 0 ? tricat("tab ", "", compinsert) : + ztrdup(compinsert)); + zsfree(compexact); if (useexact) compexact = ztrdup("accept"); else { @@ -737,35 +804,59 @@ callcompfunc(char *s, char *fn) else uselist = 0; forcelist = (complist && strstr(complist, "force")); - onlyexpl = (complist && strstr(complist, "expl")); + onlyexpl = (complist ? ((strstr(complist, "expl") ? 1 : 0) | + (strstr(complist, "messages") ? 2 : 0)) : 0); if (!compinsert) useline = 0; + else if (strstr(compinsert, "tab")) + useline = -1; else if (!strcmp(compinsert, "unambig") || !strcmp(compinsert, "unambiguous") || !strcmp(compinsert, "automenu-unambiguous")) useline = 1, usemenu = 0; - else if (!strcmp(compinsert, "menu")) - useline = 1, usemenu = 1; - else if (!strcmp(compinsert, "auto") || - !strcmp(compinsert, "automenu")) - useline = 1, usemenu = 2; else if (!strcmp(compinsert, "all")) useline = 2, usemenu = 0; else if (idigit(*compinsert)) { +#if 0 + /* group-numbers in compstate[insert] */ char *m; - +#endif useline = 1; usemenu = 3; insmnum = atoi(compinsert); +#if 0 + /* group-numbers in compstate[insert] */ if ((m = strchr(compinsert, ':'))) { insgroup = 1; insgnum = atoi(m + 1); } +#endif insspace = (compinsert[strlen(compinsert) - 1] == ' '); - } else - useline = usemenu = 0; - startauto = (compinsert && - !strcmp(compinsert, "automenu-unambiguous")); + } else { + char *p; + + if (strpfx("menu", compinsert)) + useline = 1, usemenu = 1; + else if (strpfx("auto", compinsert)) + useline = 1, usemenu = 2; + else + useline = usemenu = 0; + + if (useline && (p = strchr(compinsert, ':'))) { + insmnum = atoi(++p); +#if 0 + /* group-numbers in compstate[insert] */ + if ((p = strchr(p, ':'))) { + insgroup = 1; + insgnum = atoi(p + 1); + } +#endif + } + } + startauto = ((compinsert && + !strcmp(compinsert, "automenu-unambiguous")) || + (bashlistfirst && isset(AUTOMENU) && + (!compinsert || !*compinsert))); useexact = (compexact && !strcmp(compexact, "accept")); if (!comptoend || !*comptoend) @@ -802,16 +893,22 @@ static int makecomplist(char *s, int incmd, int lst) { char *p; + int owb = wb, owe = we, ooffs = offs; /* Inside $... ? */ - if (compfunc && (p = check_param(s, 0, 0))) + if (compfunc && (p = check_param(s, 0, 0))) { s = p; + parwb = owb; + parwe = owe; + paroffs = ooffs; + } else + parwb = -1; linwhat = inwhat; if (compfunc) { char *os = s; - int onm = nmatches, osi = movefd(0); + int onm = nmatches, odm = diffmatches, osi = movefd(0); bmatchers = NULL; mstack = NULL; @@ -827,8 +924,13 @@ makecomplist(char *s, int incmd, int lst) mnum = 0; unambig_mnum = -1; isuf = NULL; - insmnum = insgnum = 1; - insgroup = oldlist = oldins = 0; + insmnum = 1; +#if 0 + /* group-numbers in compstate[insert] */ + insgnum = 1; + insgroup = 0; +#endif + oldlist = oldins = 0; begcmgroup("default", 0); menucmp = menuacc = newmatches = onlyexpl = 0; @@ -841,11 +943,12 @@ makecomplist(char *s, int incmd, int lst) if (oldlist) { nmatches = onm; + diffmatches = odm; validlist = 1; amatches = lastmatches; lmatches = lastlmatches; if (pmatches) { - freematches(pmatches); + freematches(pmatches, 1); pmatches = NULL; hasperm = 0; } @@ -854,7 +957,7 @@ makecomplist(char *s, int incmd, int lst) return 0; } if (lastmatches) { - freematches(lastmatches); + freematches(lastmatches, 1); lastmatches = NULL; } permmatches(1); @@ -868,7 +971,7 @@ makecomplist(char *s, int incmd, int lst) hasperm = 0; hasoldlist = 1; - if (nmatches && !errflag) { + if ((nmatches || nmessages) && !errflag) { validlist = 1; redup(osi, 0); @@ -1041,7 +1144,7 @@ check_param(char *s, int set, int test) } /* Save the prefix. */ if (compfunc) { - parflags = (br >= 2 ? CMF_PARBR : 0); + parflags = (br >= 2 ? CMF_PARBR | (nest ? CMF_PARNEST : 0) : 0); sav = *b; *b = '\0'; untokenize(parpre = ztrdup(s)); @@ -1078,6 +1181,30 @@ rembslash(char *s) return t; } +/* Remove one of every pair of single quotes, without copying. Return + * the number of removed quotes. */ + +/**/ +mod_export int +remsquote(char *s) +{ + int ret = 0, qa = (isset(RCQUOTES) ? 1 : 3); + char *t = s; + + while (*s) + if (qa == 1 ? + (s[0] == '\'' && s[1] == '\'') : + (s[0] == '\'' && s[1] == '\\' && s[2] == '\'' && s[3] == '\'')) { + ret += qa; + *t++ = '\''; + s += qa + 1; + } else + *t++ = *s++; + *t = '\0'; + + return ret; +} + /* This should probably be moved into tokenize(). */ /**/ @@ -1147,8 +1274,9 @@ set_comp_sep(void) LinkList foo = newlinklist(); LinkNode n; int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs; - int tl, got = 0, i = 0, cur = -1, oll = ll, sl, remq; - int ois = instring, oib = inbackt, noffs = lp; + int tl, got = 0, i = 0, j, cur = -1, oll = ll, sl, css = 0; + int remq = 0, dq = 0, odq, sq = 0, osq, issq = 0, sqq = 0, lsq = 0, qa = 0; + int ois = instring, oib = inbackt, noffs = lp, ona = noaliases; char *tmp, *p, *ns, *ol = (char *) line, sav, *qp, *qs, *ts, qc = '\0'; s += lip; @@ -1169,8 +1297,37 @@ set_comp_sep(void) memcpy(tmp + 1, s, noffs); tmp[(scs = cs = 1 + noffs)] = 'x'; strcpy(tmp + 2 + noffs, s + noffs); - if ((remq = (*compqstack == '\\'))) + + switch (*compqstack) { + case '\\': + remq = 1; tmp = rembslash(tmp); + break; + case '\'': + issq = 1; + if (isset(RCQUOTES)) + qa = 1; + else + qa = 3; + + sq = remsquote(tmp); + + break; + case '"': + for (j = 0, p = tmp; *p; p++, j++) + if (*p == '\\' && p[1] == '\\') { + dq++; + chuck(p); + if (j > cs) { + cs++; + css++; + } + if (!*p) + break; + } + } + odq = dq; + osq = sq; inpush(dupstrspace(tmp), 0, NULL); line = (unsigned char *) tmp; ll = tl - 1; @@ -1183,9 +1340,10 @@ set_comp_sep(void) if (!tokstr) break; - for (j = 0, p = tokstr; *p; p++) + for (j = 0, p = tokstr; *p; p++) { if (*p == Snull || *p == Dnull) j++; + } if (j & 1) { tok = STRING; if (p > tokstr && p[-1] == ' ') @@ -1194,23 +1352,44 @@ set_comp_sep(void) } if (tok == ENDINPUT || tok == LEXERR) break; - if (tokstr && *tokstr) + if (tokstr && *tokstr) { + for (p = tokstr; dq && *p; p++) { + if (*p == Bnull) { + dq--; + if (p[1] == '\\') + dq--; + } + } + if (issq) { + for (p = tokstr, lsq = 0; *p; p++) { + if (sq && *p == Snull) + sq -= qa; + if (*p == '\'') { + sq -= qa; + lsq += qa; + } + } + } + else + lsq = 0; addlinknode(foo, (p = ztrdup(tokstr))); + } else p = NULL; if (!got && !zleparse) { DPUTS(!p, "no current word in substr"); got = 1; cur = i; - swb = wb - 1; - swe = we - 1; - soffs = cs - swb; + swb = wb - 1 - dq - sq; + swe = we - 1 - dq - sq; + sqq = lsq; + soffs = cs - swb - css; chuck(p + soffs); ns = dupstring(p); } i++; } while (tok != ENDINPUT && tok != LEXERR); - noaliases = 0; + noaliases = ona; strinend(); inpop(); errflag = zleparse = 0; @@ -1255,8 +1434,15 @@ set_comp_sep(void) for (p = ns, i = swb; *p; p++, i++) { if (INULL(*p)) { if (i < scs) { - if (remq && *p == Bnull && p[1]) - swb -= 2; + if (*p == Bnull) { + if (p[1] && remq) + swb -= 2; + if (odq) { + swb--; + if (p[1] == '\\') + swb--; + } + } } if (p[1] || *p != Bnull) { if (*p == Bnull) { @@ -1281,9 +1467,9 @@ set_comp_sep(void) if (ql > rl) swb -= ql - rl; } - sav = s[(i = swb - 1)]; + sav = s[(i = swb - 1 - sqq)]; s[i] = '\0'; - qp = rembslash(s); + qp = (issq ? dupstring(s) : rembslash(s)); s[i] = sav; if (swe < swb) swe = swb; @@ -1291,14 +1477,17 @@ set_comp_sep(void) sl = strlen(s); if (swe > sl) { swe = sl; - if (strlen(ns) > swe - swb + 1) + if ((int)strlen(ns) > swe - swb + 1) ns[swe - swb + 1] = '\0'; } - qs = rembslash(s + swe); + qs = (issq ? dupstring(s + swe) : rembslash(s + swe)); sl = strlen(ns); if (soffs > sl) soffs = sl; - + if (issq) { + remsquote(qp); + remsquote(qs); + } { int set = CP_QUOTE | CP_QUOTING, unset = 0; @@ -1343,6 +1532,10 @@ set_comp_sep(void) untokenize(ss); compsuffix = ztrdup(ss); } + if ((i = strlen(compprefix)) > 1 && compprefix[i - 1] == '\\' && + compprefix[i - 2] != '\\' && compprefix[i - 2] != Meta) + compprefix[i - 1] = '\0'; + tmp = tricat(compqiprefix, compiprefix, multiquote(qp, 1)); zsfree(compqiprefix); compqiprefix = tmp; @@ -1369,11 +1562,11 @@ set_comp_sep(void) return 0; } -/* This stores the strings from the list in an array. */ +/* This builds an array from a list of strings. */ /**/ -mod_export void -set_list_array(char *name, LinkList l) +mod_export char ** +bld_list_array(LinkList l) { char **a, **p; LinkNode n; @@ -1383,7 +1576,16 @@ set_list_array(char *name, LinkList l) *p++ = ztrdup((char *) getdata(n)); *p = NULL; - setaparam(name, a); + return a; +} + +/* This stores the strings from the list in an array. */ + +/**/ +mod_export void +set_list_array(char *name, LinkList l) +{ + setaparam(name, bld_list_array(l)); } /* Get the words from a variable or a (list of words). */ @@ -1437,18 +1639,72 @@ get_user_var(char *nam) /* Otherwise it should be a parameter name. */ char **arr = NULL, *val; + queue_signals(); if ((arr = getaparam(nam)) || (arr = gethparam(nam))) - return (incompfunc ? arrdup(arr) : arr); - - if ((val = getsparam(nam))) { + arr = (incompfunc ? arrdup(arr) : arr); + else if ((val = getsparam(nam))) { arr = (char **) zhalloc(2*sizeof(char *)); arr[0] = (incompfunc ? dupstring(val) : val); arr[1] = NULL; } + unqueue_signals(); return arr; } } +static char ** +get_data_arr(char *name, int keys) +{ + struct value vbuf; + char **ret; + Value v; + + queue_signals(); + if (!(v = fetchvalue(&vbuf, &name, 1, + (keys ? SCANPM_WANTKEYS : SCANPM_WANTVALS) | + SCANPM_MATCHMANY))) + ret = NULL; + else + ret = getarrvalue(v); + unqueue_signals(); + + 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. */ @@ -1460,10 +1716,11 @@ addmatches(Cadata dat, char **argv) char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; 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, pl, sl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; - int ppl = 0, psl = 0; + int ppl = 0, psl = 0, ilen = 0; int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern; - int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt; + int isexact, doadd, ois = instring, oib = inbackt; Cline lc = NULL, pline = NULL, sline = NULL; Cmatch cm; struct cmlist mst; @@ -1471,24 +1728,38 @@ addmatches(Cadata dat, char **argv) Patprog cp = NULL, *pign = NULL; LinkList aparl = NULL, oparl = NULL, dparl = NULL; Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; - - if (!*argv) { - SWITCHHEAPS(compheap) { - /* Select the group in which to store the matches. */ - gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | - ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | - ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); - if (dat->group) { - endcmgroup(NULL); - begcmgroup(dat->group, gflags); - } else { - endcmgroup(NULL); - begcmgroup("default", 0); - } - } SWITCHBACKHEAPS; - + Heap oldheap; + + SWITCHHEAPS(oldheap, compheap) { + if (dat->dummies) + dat->aflags = ((dat->aflags | CAF_NOSORT | CAF_UNIQCON) & + ~CAF_UNIQALL); + + /* Select the group in which to store the matches. */ + gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | + ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | + ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); + if (dat->group) { + endcmgroup(NULL); + begcmgroup(dat->group, gflags); + } else { + endcmgroup(NULL); + begcmgroup("default", 0); + } + if (dat->mesg || dat->exp) { + curexpl = (Cexpl) zhalloc(sizeof(struct cexpl)); + curexpl->always = !!dat->mesg; + curexpl->count = curexpl->fcount = 0; + curexpl->str = dupstring(dat->mesg ? dat->mesg : dat->exp); + if (dat->mesg) + addexpl(1); + } else + curexpl = NULL; + } SWITCHBACKHEAPS(oldheap); + + if (!*argv && !dat->dummies && !(dat->aflags & CAF_ALL)) return 1; - } + for (bp = brbeg; bp; bp = bp->next) bp->curpos = ((dat->aflags & CAF_QUOTE) ? bp->pos : bp->qpos); for (bp = brend; bp; bp = bp->next) @@ -1521,7 +1792,7 @@ addmatches(Cadata dat, char **argv) /* Switch back to the heap that was used when the completion widget * was invoked. */ - SWITCHHEAPS(compheap) { + SWITCHHEAPS(oldheap, compheap) { if ((doadd = (!dat->apar && !dat->opar && !dat->dpar))) { if (dat->aflags & CAF_MATCH) hasmatched = 1; @@ -1539,13 +1810,6 @@ addmatches(Cadata dat, char **argv) dparr = NULL; dparl = newlinklist(); } - if (dat->exp) { - curexpl = (Cexpl) zhalloc(sizeof(struct cexpl)); - curexpl->count = curexpl->fcount = 0; - curexpl->str = dupstring(dat->exp); - } else - curexpl = NULL; - /* Store the matcher in our stack of matchers. */ if (dat->match) { mst.next = mstack; @@ -1597,6 +1861,11 @@ addmatches(Cadata dat, char **argv) lsuf = dupstring(compsuffix); llpl = strlen(lpre); llsl = strlen(lsuf); + + if (llpl + (int)strlen(compqiprefix) + (int)strlen(lipre) != origlpre + || llsl + (int)strlen(compqisuffix) + (int)strlen(lisuf) != origlsuf) + lenchanged = 1; + /* Test if there is an existing -P prefix. */ if (dat->pre && *dat->pre) { pl = pfxlen(dat->pre, lpre); @@ -1649,55 +1918,57 @@ addmatches(Cadata dat, char **argv) llpl -= gfl; } } - s = dat->ppre ? dat->ppre : ""; - if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) { - if (matchsubs) { - Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0); - - tmp->prefix = matchsubs; - if (matchlastpart) - matchlastpart->next = tmp; + if ((s = dat->ppre)) { + if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) { + if (matchsubs) { + Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0); + + tmp->prefix = matchsubs; + if (matchlastpart) + matchlastpart->next = tmp; + else + matchparts = tmp; + } + pline = matchparts; + lpre += ml; + llpl -= ml; + bcp = ml; + bpadd = strlen(s) - ml; + } else { + if (llpl <= lpl && strpfx(lpre, s)) + lpre = dupstring(""); + else if (llpl > lpl && strpfx(s, lpre)) + lpre += lpl; else - matchparts = tmp; + *argv = NULL; + bcp = lpl; } - pline = matchparts; - lpre += ml; - llpl -= ml; - bcp = ml; - bpadd = strlen(s) - ml; - } else { - if (llpl <= lpl && strpfx(lpre, s)) - lpre = ""; - else if (llpl > lpl && strpfx(s, lpre)) - lpre += lpl; - else - *argv = NULL; - bcp = lpl; } - s = dat->psuf ? dat->psuf : ""; - if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) { - if (matchsubs) { - Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, CLF_SUF); - - tmp->suffix = matchsubs; - if (matchlastpart) - matchlastpart->next = tmp; + if ((s = dat->psuf)) { + if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) { + if (matchsubs) { + Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, CLF_SUF); + + tmp->suffix = matchsubs; + if (matchlastpart) + matchlastpart->next = tmp; + else + matchparts = tmp; + } + sline = revert_cline(matchparts); + lsuf[llsl - ml] = '\0'; + llsl -= ml; + bcs = ml; + bsadd = strlen(s) - ml; + } else { + if (llsl <= lsl && strsfx(lsuf, s)) + lsuf = dupstring(""); + else if (llsl > lsl && strsfx(s, lsuf)) + lsuf[llsl - lsl] = '\0'; else - matchparts = tmp; + *argv = NULL; + bcs = lsl; } - sline = revert_cline(matchparts); - lsuf[llsl - ml] = '\0'; - llsl -= ml; - bcs = ml; - bsadd = strlen(s) - ml; - } else { - if (llsl <= lsl && strsfx(lsuf, s)) - lsuf = ""; - else if (llsl > lsl && strsfx(s, lsuf)) - lsuf[llsl - lsl] = '\0'; - else - *argv = NULL; - bcs = lsl; } if (comppatmatch && *comppatmatch) { int is = (*comppatmatch == '*'); @@ -1721,17 +1992,6 @@ addmatches(Cadata dat, char **argv) } } } - /* Select the group in which to store the matches. */ - gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | - ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | - ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); - if (dat->group) { - endcmgroup(NULL); - begcmgroup(dat->group, gflags); - } else { - endcmgroup(NULL); - begcmgroup("default", 0); - } if (*argv) { if (dat->pre) dat->pre = dupstring(dat->pre); @@ -1743,7 +2003,6 @@ addmatches(Cadata dat, char **argv) } else dat->prpre = dupstring(dat->prpre); /* Select the set of matches. */ - oisalt = (dat->aflags & CAF_ALT); if (dat->remf) { dat->remf = dupstring(dat->remf); @@ -1761,17 +2020,28 @@ addmatches(Cadata dat, char **argv) /* Walk through the matches given. */ obpl = bpl; obsl = bsl; - if (!oisalt && (aign || pign)) { - int max = 0; - char **ap = argv; - - ppl = (dat->ppre ? strlen(dat->ppre) : 0); - while ((s = *ap++)) - if ((sl = strlen(s)) > max) - max = sl; - psl = (dat->psuf ? strlen(dat->psuf) : 0); - ibuf = (char *) zhalloc(1 + ppl + max + psl); + if (dat->aflags & CAF_ARRAYS) { + Heap oldheap2; + + SWITCHHEAPS(oldheap2, oldheap) { + arrays = argv; + argv = NULL; + while (*arrays && + (!(argv = get_data_arr(*arrays, + (dat->aflags & CAF_KEYS))) || + !*argv)) + arrays++; + arrays++; + if (!argv) { + ms = NULL; + argv = &ms; + } + } SWITCHBACKHEAPS(oldheap2); } + if (dat->ppre) + ppl = strlen(dat->ppre); + if (dat->psuf) + psl = strlen(dat->psuf); for (; (s = *argv); argv++) { bpl = obpl; bsl = obsl; @@ -1780,9 +2050,11 @@ addmatches(Cadata dat, char **argv) disp = NULL; } sl = strlen(s); - isalt = oisalt; - if (!isalt && (aign || pign)) { - int il = ppl + sl + psl; + if (aign || pign) { + int il = ppl + sl + psl, addit = 1; + + if (il + 1> ilen) + ibuf = (char *) zhalloc((ilen = il) + 2); if (ppl) memcpy(ibuf, dat->ppre, ppl); @@ -1796,15 +2068,21 @@ addmatches(Cadata dat, char **argv) char **pt = aign; int filell; - for (isalt = 0; !isalt && *pt; pt++) - isalt = ((filell = strlen(*pt)) < il && - !strcmp(*pt, ibuf + il - filell)); + for (; addit && *pt; pt++) + addit = !((filell = strlen(*pt)) < il && + !strcmp(*pt, ibuf + il - filell)); } - if (!isalt && pign) { + if (addit && pign) { Patprog *pt = pign; - for (isalt = 0; !isalt && *pt; pt++) - isalt = pattry(*pt, ibuf); + for (; addit && *pt; pt++) + addit = !pattry(*pt, ibuf); + } + if (!addit) { + compignored++; + if (dparr && !*++dparr) + dparr = NULL; + goto next_array; } } if (!(dat->aflags & CAF_MATCH)) { @@ -1822,7 +2100,7 @@ addmatches(Cadata dat, char **argv) &isexact))) { if (dparr && !*++dparr) dparr = NULL; - continue; + goto next_array; } if (doadd) { Brinfo bp; @@ -1832,7 +2110,7 @@ addmatches(Cadata dat, char **argv) for (bp = obsl; bp; bp = bp->next) bp->curpos += bsadd; - if ((cm = add_match_data(isalt, ms, lc, dat->ipre, NULL, + if ((cm = add_match_data(0, ms, s, lc, dat->ipre, NULL, dat->isuf, dat->pre, dat->prpre, dat->ppre, pline, dat->psuf, sline, @@ -1854,6 +2132,25 @@ addmatches(Cadata dat, char **argv) } free_cline(lc); } + next_array: + if ((dat->aflags & CAF_ARRAYS) && !argv[1]) { + Heap oldheap2; + + SWITCHHEAPS(oldheap2, oldheap) { + argv = NULL; + while (*arrays && + (!(argv = get_data_arr(*arrays, + (dat->aflags & CAF_KEYS))) || + !*argv)) + arrays++; + arrays++; + if (!argv) { + ms = NULL; + argv = &ms; + } + argv--; + } SWITCHBACKHEAPS(oldheap2); + } } if (dat->apar) set_list_array(dat->apar, aparl); @@ -1862,8 +2159,15 @@ addmatches(Cadata dat, char **argv) if (dat->dpar) set_list_array(dat->dpar, dparl); if (dat->exp) - addexpl(); - } SWITCHBACKHEAPS; + addexpl(0); + if (!hasallmatch && (dat->aflags & CAF_ALL)) { + 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 * matchers. */ @@ -1887,7 +2191,7 @@ addmatches(Cadata dat, char **argv) /**/ mod_export Cmatch -add_match_data(int alt, char *str, Cline line, +add_match_data(int alt, char *str, char *orig, Cline line, char *ipre, char *ripre, char *isuf, char *pre, char *prpre, char *ppre, Cline pline, @@ -1977,7 +2281,7 @@ add_match_data(int alt, char *str, Cline line, sl = tsl; } if (qisl) { - Cline qsl = bld_parts(qisuf, qisl, qisl, NULL); + Cline qsl = bld_parts(dupstring(qisuf), qisl, qisl, NULL); qsl->flags |= CLF_SUF; qsl->suffix = qsl->prefix; @@ -2060,7 +2364,7 @@ add_match_data(int alt, char *str, Cline line, line = p; } if (qipl) { - Cline lp, p = bld_parts(qipre, qipl, qipl, &lp); + Cline lp, p = bld_parts(dupstring(qipre), qipl, qipl, &lp); lp->next = line; line = p; @@ -2115,6 +2419,7 @@ add_match_data(int alt, char *str, Cline line, /* Allocate and fill the match structure. */ cm = (Cmatch) zhalloc(sizeof(struct cmatch)); cm->str = str; + cm->orig = dupstring(orig); cm->ppre = (ppre && *ppre ? ppre : NULL); cm->psuf = (psuf && *psuf ? psuf : NULL); cm->prpre = ((flags & CMF_FILE) && prpre && *prpre ? prpre : NULL); @@ -2133,7 +2438,22 @@ add_match_data(int alt, char *str, Cline line, (complist ? ((strstr(complist, "packed") ? CMF_PACKED : 0) | (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); - + cm->mode = 0; + cm->modec = '\0'; + if ((flags & CMF_FILE) && orig[0] && orig[strlen(orig) - 1] != '/') { + struct stat buf; + char *pb; + + pb = (char *) zhalloc((cm->prpre ? strlen(cm->prpre) : 0) + + 3 + strlen(orig)); + sprintf(pb, "%s%s", (cm->prpre ? cm->prpre : "./"), orig); + + if (!ztat(pb, &buf, 1)) { + cm->mode = buf.st_mode; + if ((cm->modec = file_type(buf.st_mode)) == ' ') + cm->modec = '\0'; + } + } if ((*compqstack == '\\' && compqstack[1]) || (autoq && *compqstack && compqstack[1] == '\\')) cm->flags |= CMF_NOSPACE; @@ -2175,6 +2495,8 @@ add_match_data(int alt, char *str, Cline line, newmatches = 1; mgroup->new = 1; + if (alt) + compignored++; if (!complastprompt || !*complastprompt) dolastprompt = 0; @@ -2221,7 +2543,7 @@ add_match_data(int alt, char *str, Cline line, comp_setunset(0, 0, CP_EXACTSTR, 0); } ai->exactm = cm; - } else if (useexact) { + } else if (useexact && !matcheq(cm, ai->exactm)) { ai->exact = 2; ai->exactm = NULL; if (incompfunc) @@ -2258,13 +2580,14 @@ begcmgroup(char *n, int flags) } mgroup = (Cmgroup) zhalloc(sizeof(struct cmgroup)); mgroup->name = dupstring(n); - mgroup->lcount = mgroup->llcount = mgroup->mcount = 0; + mgroup->lcount = mgroup->llcount = mgroup->mcount = mgroup->ecount = + mgroup->ccount = 0; mgroup->flags = flags; mgroup->matches = NULL; mgroup->ylist = NULL; mgroup->expls = NULL; mgroup->perm = NULL; - mgroup->new = 0; + mgroup->new = mgroup->num = mgroup->nbrbeg = mgroup->nbrend = 0; mgroup->lexpls = expls = newlinklist(); mgroup->lmatches = matches = newlinklist(); @@ -2272,7 +2595,9 @@ begcmgroup(char *n, int flags) mgroup->lallccs = allccs = ((flags & CGF_NOSORT) ? NULL : newlinklist()); - mgroup->next = amatches; + if ((mgroup->next = amatches)) + amatches->prev = mgroup; + mgroup->prev = NULL; amatches = mgroup; } @@ -2289,7 +2614,7 @@ endcmgroup(char **ylist) /**/ mod_export void -addexpl(void) +addexpl(int always) { LinkNode n; Cexpl e; @@ -2299,12 +2624,21 @@ addexpl(void) if (!strcmp(curexpl->str, e->str)) { e->count += curexpl->count; e->fcount += curexpl->fcount; - + if (always) { + e->always = 1; + nmessages++; + newmatches = 1; + mgroup->new = 1; + } return; } } addlinknode(expls, curexpl); newmatches = 1; + if (always) { + mgroup->new = 1; + nmessages++; + } } /* The comparison function for matches (used for sorting). */ @@ -2425,6 +2759,8 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) } } else { 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)) @@ -2433,6 +2769,17 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) n--; } *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; + } } } else if (!(flags & CGF_UNIQCON)) { int dup; @@ -2476,9 +2823,10 @@ dupmatch(Cmatch m, int nbeg, int nend) { Cmatch r; - r = (Cmatch) zcalloc(sizeof(struct cmatch)); + r = (Cmatch) zshcalloc(sizeof(struct cmatch)); r->str = ztrdup(m->str); + r->orig = ztrdup(m->orig); r->ipre = ztrdup(m->ipre); r->ripre = ztrdup(m->ripre); r->isuf = ztrdup(m->isuf); @@ -2488,7 +2836,7 @@ dupmatch(Cmatch m, int nbeg, int nend) r->pre = ztrdup(m->pre); r->suf = ztrdup(m->suf); r->flags = m->flags; - if (nbeg) { + if (m->brpl) { int *p, *q, i; r->brpl = (int *) zalloc(nbeg * sizeof(int)); @@ -2497,7 +2845,7 @@ dupmatch(Cmatch m, int nbeg, int nend) *p = *q; } else r->brpl = NULL; - if (nend) { + if (m->brsl) { int *p, *q, i; r->brsl = (int *) zalloc(nend * sizeof(int)); @@ -2512,6 +2860,8 @@ dupmatch(Cmatch m, int nbeg, int nend) r->qipl = m->qipl; r->qisl = m->qisl; r->disp = ztrdup(m->disp); + r->mode = m->mode; + r->modec = m->modec; return r; } @@ -2538,7 +2888,7 @@ permmatches(int last) opm = pmatches; pmatches = lmatches = NULL; - nmatches = smatches = 0; + nmatches = smatches = diffmatches = 0; if (!ainfo->count) { if (last) @@ -2570,11 +2920,14 @@ permmatches(int last) nmatches += g->mcount; smatches += g->lcount; - n = (Cmgroup) zcalloc(sizeof(struct cmgroup)); + if (g->mcount > 1) + diffmatches = 1; + + n = (Cmgroup) zshcalloc(sizeof(struct cmgroup)); if (g->perm) { g->perm->next = NULL; - freematches(g->perm); + freematches(g->perm, 0); } g->perm = n; @@ -2588,7 +2941,7 @@ permmatches(int last) n->num = gn++; n->flags = g->flags; n->mcount = g->mcount; - n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch)); + n->matches = p = (Cmatch *) zshcalloc((n->mcount + 1) * sizeof(Cmatch)); n->name = ztrdup(g->name); for (q = g->matches; *q; q++, p++) *p = dupmatch(*q, nbrbeg, nbrend); @@ -2602,10 +2955,12 @@ permmatches(int last) n->ylist = NULL; if ((n->ecount = g->ecount)) { - n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl)); + n->expls = ep = (Cexpl *) zshcalloc((n->ecount + 1) * sizeof(Cexpl)); for (eq = g->expls; (o = *eq); eq++, ep++) { - *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl)); + *ep = e = (Cexpl) zshcalloc(sizeof(struct cexpl)); e->count = (fi ? o->fcount : o->count); + e->always = o->always; + e->fcount = 0; e->str = ztrdup(o->str); } *ep = NULL; @@ -2624,18 +2979,29 @@ permmatches(int last) nmatches += g->mcount; smatches += g->lcount; + + if (g->mcount > 1) + diffmatches = 1; + g->num = gn++; } g->new = 0; g = g->next; } - for (g = pmatches; g; g = g->next) { + for (g = pmatches, p = NULL; g; g = g->next) { g->nbrbeg = nbrbeg; g->nbrend = nbrend; for (rn = 1, q = g->matches; *q; q++) { (*q)->rnum = rn++; (*q)->gnum = mn++; } + if (!diffmatches && *g->matches) { + if (p) { + if (!matcheq(*g->matches, *p)) + diffmatches = 1; + } else + p = g->matches; + } } hasperm = 1; permmnum = mn - 1; @@ -2654,6 +3020,7 @@ freematch(Cmatch m, int nbeg, int nend) if (!m) return; zsfree(m->str); + zsfree(m->orig); zsfree(m->ipre); zsfree(m->ripre); zsfree(m->isuf); @@ -2666,8 +3033,10 @@ freematch(Cmatch m, int nbeg, int nend) zsfree(m->remf); zsfree(m->disp); zsfree(m->autoq); - zfree(m->brpl, nbeg * sizeof(int)); - zfree(m->brsl, nend * sizeof(int)); + if (m->brpl) + zfree(m->brpl, nbeg * sizeof(int)); + if (m->brsl) + zfree(m->brsl, nend * sizeof(int)); zfree(m, sizeof(m)); } @@ -2676,7 +3045,7 @@ freematch(Cmatch m, int nbeg, int nend) /**/ mod_export void -freematches(Cmgroup g) +freematches(Cmgroup g, int cm) { Cmgroup n; Cmatch *m; @@ -2687,6 +3056,7 @@ freematches(Cmgroup g) for (m = g->matches; *m; m++) freematch(*m, g->nbrbeg, g->nbrend); + free(g->matches); if (g->ylist) freearray(g->ylist); @@ -2704,4 +3074,6 @@ freematches(Cmgroup g) g = n; } + if (cm) + minfo.cur = NULL; } |