diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/compcore.c | 4 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 34 | ||||
-rw-r--r-- | Src/Zle/complete.c | 4 | ||||
-rw-r--r-- | Src/Zle/complist.c | 15 | ||||
-rw-r--r-- | Src/Zle/compmatch.c | 57 | ||||
-rw-r--r-- | Src/Zle/computil.c | 356 | ||||
-rw-r--r-- | Src/Zle/textobjects.c | 9 | ||||
-rw-r--r-- | Src/Zle/zle.h | 7 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 17 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 8 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 11 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 12 | ||||
-rw-r--r-- | Src/Zle/zle_thingy.c | 27 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 47 |
15 files changed, 315 insertions, 295 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index d1cf7a08a..52b0c173f 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -3135,7 +3135,9 @@ matchcmp(Cmatch *a, Cmatch *b) if ((*b)->disp && !((*b)->flags & CMF_MORDER)) return 1; - return zstrbcmp((*a)->str, (*b)->str); + return zstrcmp((*a)->str, (*b)->str, (SORTIT_IGNORING_BACKSLASHES| + (isset(NUMERICGLOBSORT) ? + SORTIT_NUMERICALLY : 0))); } /* This tests whether two matches are equal (would produce the same diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 52c6f1233..5414b8ff6 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -99,7 +99,7 @@ freecompctlp(HashNode hn) } /**/ -void +static void freecompctl(Compctl cc) { if (cc == &cc_default || @@ -142,7 +142,7 @@ freecompctl(Compctl cc) } /**/ -void +static void freecompcond(void *a) { Compcond cc = (Compcond) a; @@ -186,7 +186,7 @@ freecompcond(void *a) } /**/ -int +static int compctlread(char *name, char **args, Options ops, char *reply) { char *buf, *bptr; @@ -1564,6 +1564,8 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) Compctl cc = NULL; int ret = 0; + queue_signals(); + /* clear static flags */ cclist = 0; showmask = 0; @@ -1571,12 +1573,15 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) /* Parse all the arguments */ if (*argv) { /* Let's see if this is a global matcher definition. */ - if ((ret = get_gmatcher(name, argv))) + if ((ret = get_gmatcher(name, argv))) { + unqueue_signals(); return ret - 1; + } cc = (Compctl) zshcalloc(sizeof(*cc)); if (get_compctl(name, &argv, cc, 1, 0, 0)) { freecompctl(cc); + unqueue_signals(); return 1; } @@ -1604,6 +1609,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) printcompctl((cclist & COMP_LIST) ? "" : "DEFAULT", &cc_default, 0, 0); printcompctl((cclist & COMP_LIST) ? "" : "FIRST", &cc_first, 0, 0); print_gmatcher((cclist & COMP_LIST)); + unqueue_signals(); return ret; } @@ -1642,6 +1648,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) printcompctl("", &cc_first, 0, 0); if (cclist & COMP_LISTMATCH) print_gmatcher(COMP_LIST); + unqueue_signals(); return ret; } @@ -1656,6 +1663,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) compctl_process_cc(argv, cc); } + unqueue_signals(); return ret; } @@ -1667,12 +1675,18 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) static int bin_compcall(char *name, UNUSED(char **argv), Options ops, UNUSED(int func)) { + int ret; + if (incompfunc != 1) { zwarnnam(name, "can only be called from completion function"); return 1; } - return makecomplistctl((OPT_ISSET(ops,'T') ? 0 : CFN_FIRST) | - (OPT_ISSET(ops,'D') ? 0 : CFN_DEFAULT)); + + queue_signals(); + ret = makecomplistctl((OPT_ISSET(ops,'T') ? 0 : CFN_FIRST) | + (OPT_ISSET(ops,'D') ? 0 : CFN_DEFAULT)); + unqueue_signals(); + return ret; } /* @@ -1756,6 +1770,8 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) int onm = nmatches, odm = diffmatches, osi = movefd(0); LinkNode n; + queue_signals(); + /* We build a copy of the list of matchers to use to make sure that this * works even if a shell function called from the completion code changes * the global matchers. */ @@ -1851,6 +1867,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) redup(osi, 0); dat->lst = 0; + unqueue_signals(); return 0; } if (lastmatches) { @@ -1874,6 +1891,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) redup(osi, 0); dat->lst = 0; + unqueue_signals(); return 0; } if (!m || !(m = m->next)) @@ -1883,6 +1901,8 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) } redup(osi, 0); dat->lst = 1; + + unqueue_signals(); return 0; } @@ -2044,7 +2064,7 @@ maketildelist(void) /* This does the check for compctl -x `n' and `N' patterns. */ /**/ -int +static int getcpat(char *str, int cpatindex, char *cpat, int class) { char *s, *t, *p; diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 48fcd4751..68bdf2332 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -901,7 +901,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) return 0; singsub(&sa); - pp = patcompile(sa, PAT_STATIC, NULL); + pp = patcompile(sa, PAT_HEAPDUP, NULL); for (i--, p = compwords + i; i >= 0; p--, i--) { if (pattry(pp, *p)) { @@ -955,7 +955,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) if (!na) return 0; - if (!(pp = patcompile(sa, PAT_STATIC, 0))) + if (!(pp = patcompile(sa, PAT_HEAPDUP, 0))) return 0; if (test == CVT_PREPAT) { diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 2edaf6eca..a83daeff9 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -1993,7 +1993,8 @@ complistmatches(UNUSED(Hookdef dummy), Chdata dat) if (noselect > 0) noselect = 0; - if ((minfo.asked == 2 && mselect < 0) || nlnct >= zterm_lines) { + if ((minfo.asked == 2 && mselect < 0) || nlnct >= zterm_lines || + errflag) { showinglist = 0; amatches = oamatches; return (noselect = 1); @@ -2333,11 +2334,6 @@ msearch(Cmatch **ptr, char *ins, int back, int rep, int *wrapp) } } if (x == ex && y == ey) { - if (wrap) { - msearchstate = MS_FAILED | owrap; - break; - } - msearchstate |= MS_WRAPPED; if (back) { x = mcols - 1; @@ -2349,6 +2345,13 @@ msearch(Cmatch **ptr, char *ins, int back, int rep, int *wrapp) } ex = mcol; ey = mline; + + if (wrap || (x == ex && y == ey)) { + msearchstate = MS_FAILED | owrap; + break; + } + + msearchstate |= MS_WRAPPED; wrap = 1; *wrapp = 1; } diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index aedf463fc..1cdbb8a48 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -1548,27 +1548,11 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws) { convchar_t c, wc; convchar_t ind, wind; - int len = 0, wlen, mt, wmt; -#ifdef MULTIBYTE_SUPPORT - mbstate_t lstate, wstate; - - memset(&lstate, 0, sizeof(lstate)); - memset(&wstate, 0, sizeof(wstate)); -#endif + int len = 0, wlen = 0, mt, wmt; while (p && wp && *s && *ws) { /* First test the word character */ -#ifdef MULTIBYTE_SUPPORT - wlen = mb_metacharlenconv_r(ws, &wc, &wstate); -#else - if (*ws == Meta) { - wc = STOUC(ws[1]) ^ 32; - wlen = 2; - } else { - wc = STOUC(*ws); - wlen = 1; - } -#endif + wc = unmeta_one(ws, &wlen); wind = pattern_match1(wp, wc, &wmt); if (!wind) return 0; @@ -1576,18 +1560,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws) /* * Now the line character. */ -#ifdef MULTIBYTE_SUPPORT - len = mb_metacharlenconv_r(s, &c, &lstate); -#else - /* We have the character itself. */ - if (*s == Meta) { - c = STOUC(s[1]) ^ 32; - len = 2; - } else { - c = STOUC(*s); - len = 1; - } -#endif + c = unmeta_one(s, &len); /* * If either is "?", they match each other; no further tests. * Apply this even if the character wasn't convertable; @@ -1627,17 +1600,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws) } while (p && *s) { -#ifdef MULTIBYTE_SUPPORT - len = mb_metacharlenconv_r(s, &c, &lstate); -#else - if (*s == Meta) { - c = STOUC(s[1]) ^ 32; - len = 2; - } else { - c = STOUC(*s); - len = 1; - } -#endif + c = unmeta_one(s, &len); if (!pattern_match1(p, c, &mt)) return 0; p = p->next; @@ -1645,17 +1608,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws) } while (wp && *ws) { -#ifdef MULTIBYTE_SUPPORT - wlen = mb_metacharlenconv_r(ws, &wc, &wstate); -#else - if (*ws == Meta) { - wc = STOUC(ws[1]) ^ 32; - wlen = 2; - } else { - wc = STOUC(*ws); - wlen = 1; - } -#endif + wc = unmeta_one(ws, &wlen); if (!pattern_match1(wp, wc, &wmt)) return 0; wp = wp->next; diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 192ddeab9..e704f9ffa 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -917,7 +917,6 @@ struct cadef { int argsactive; /* if normal arguments are still allowed */ /* used while parsing a command line */ char *set; /* set name prefix (<name>-), shared */ - char *sname; /* set name */ int flags; /* see CDF_* below */ char *nonarg; /* pattern for non-args (-A argument) */ }; @@ -935,7 +934,7 @@ struct caopt { Caarg args; /* option arguments */ int active; /* still allowed on command line */ int num; /* it's the num'th option */ - char *set; /* set name, shared */ + char *gsname; /* group or set name, shared */ int not; /* don't complete this option (`!...') */ }; @@ -956,10 +955,10 @@ struct caarg { char *end; /* end-pattern for ::<pat>:... */ char *opt; /* option name if for an option */ int num; /* it's the num'th argument */ - int min; /* it's also this argument, using opt. args */ + int min; /* earliest possible arg pos, given optional args */ int direct; /* true if argument number was given explicitly */ int active; /* still allowed on command line */ - char *set; /* set name, shared */ + char *gsname; /* group or set name, shared */ }; #define CAA_NORMAL 1 @@ -1020,7 +1019,6 @@ freecadef(Cadef d) s = d->snext; zsfree(d->match); zsfree(d->set); - zsfree(d->sname); if (d->defs) freearray(d->defs); @@ -1098,7 +1096,7 @@ parse_caarg(int mult, int type, int num, int opt, char *oname, char **def, ret->type = type; ret->opt = ztrdup(oname); ret->direct = 0; - ret->set = set; + ret->gsname = set; /* Get the description. */ @@ -1147,8 +1145,11 @@ alloc_cadef(char **args, int single, char *match, char *nonarg, int flags) ret->defs = NULL; ret->ndefs = 0; } + ret->nopts = 0; + ret->ndopts = 0; + ret->nodopts = 0; ret->lastt = time(0); - ret->set = ret->sname = NULL; + ret->set = NULL; if (single) { ret->single = (Caopt *) zalloc(256 * sizeof(Caopt)); memset(ret->single, 0, 256 * sizeof(Caopt)); @@ -1182,12 +1183,10 @@ parse_cadef(char *nam, char **args) Cadef all, ret; Caopt *optp; char **orig_args = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs; - char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL; + char *adpre, *adsuf, *axor = NULL, *doset = NULL, **pendset = NULL, **curset = NULL; char *nonarg = NULL; - int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0; - int state = 0, not = 0; - - nopts = ndopts = nodopts = 0; + int single = 0, anum = 1, xnum, flags = 0; + int foreignset = 0, not = 0; /* First string is the auto-description definition. */ @@ -1250,51 +1249,72 @@ parse_cadef(char *nam, char **args) if (nonarg) tokenize(nonarg = dupstring(nonarg)); - /* Looks good. Optimistically allocate the cadef structure. */ all = ret = alloc_cadef(orig_args, single, match, nonarg, flags); optp = &(ret->opts); - anum = 1; - sargs = args; /* Get the definitions. */ - for (; *args; args++) { + for (; *args || pendset; args++) { + if (!*args) { + /* start new set */ + args = sargs; /* go back and repeat parse of common options */ + doset = NULL; + set_cadef_opts(ret); + ret = ret->snext = alloc_cadef(NULL, single, match, nonarg, flags); + optp = &(ret->opts); + anum = 1; + foreignset = 0; + curset = pendset; + pendset = 0; + } if (args[0][0] == '-' && !args[0][1] && args[1]) { - if (!state) { - char *p; - int l; - - if (setp) - args = setp; - p = *++args; - l = strlen(p) - 1; + if ((foreignset = curset && args != curset)) { + if (!pendset && args > curset) + pendset = args; /* mark pointer to next pending set */ + ++args; + } else { + /* Carrying on: this is the current set */ + char *p = *++args; + int l = strlen(p) - 1; + if (*p == '(' && p[l] == ')') { axor = p = dupstring(p + 1); p[l - 1] = '\0'; } else axor = NULL; + if (!*p) { + freecadef(all); + zwarnnam(nam, "empty set name"); + return NULL; + } ret->set = doset = tricat(p, "-", ""); - ret->sname = ztrdup(p); - state = 1; - } else { - setp = args; - state = 0; - args = sargs - 1; - doset = NULL; - ret->nopts = nopts; - ret->ndopts = ndopts; - ret->nodopts = nodopts; - set_cadef_opts(ret); - ret = ret->snext = alloc_cadef(NULL, single, NULL, nonarg, flags); - optp = &(ret->opts); - nopts = ndopts = nodopts = 0; - anum = 1; + curset = args; /* needed for the first set */ } continue; - } + } else if (args[0][0] == '+' && !args[0][1] && args[1]) { + char *p; + int l; + + foreignset = 0; /* group not in any set, don't want to skip it */ + p = *++args; + l = strlen(p) - 1; + if (*p == '(' && p[l] == ')') { + axor = p = dupstring(p + 1); + p[l - 1] = '\0'; + } else + axor = NULL; + if (!*p) { + freecadef(all); + zwarnnam(nam, "empty group name"); + return NULL; + } + doset = tricat(p, "-", ""); + continue; + } else if (foreignset) /* skipping over a different set */ + continue; p = dupstring(*args); xnum = 0; if ((not = (*p == '!'))) @@ -1506,7 +1526,7 @@ parse_cadef(char *nam, char **args) optp = &((*optp)->next); opt->next = NULL; - opt->set = doset; + opt->gsname = doset; opt->name = ztrdup(rembslashcolon(name)); if (descr) opt->descr = ztrdup(descr); @@ -1526,13 +1546,13 @@ parse_cadef(char *nam, char **args) opt->xor = (again == 1 && xor ? zarrdup(xor) : xor); opt->type = otype; opt->args = oargs; - opt->num = nopts++; + opt->num = ret->nopts++; opt->not = not; if (otype == CAO_DIRECT || otype == CAO_EQUAL) - ndopts++; + ret->ndopts++; else if (otype == CAO_ODIRECT || otype == CAO_OEQUAL) - nodopts++; + ret->nodopts++; /* If this is for single-letter option we also store a * pointer for the definition in the array for fast lookup. @@ -1584,7 +1604,7 @@ parse_cadef(char *nam, char **args) continue; if ((direct = idigit(*p))) { - /* Argment number is given. */ + /* Argument number is given. */ int num = 0; while (*p && idigit(*p)) @@ -1630,9 +1650,6 @@ parse_cadef(char *nam, char **args) ret->args = arg; } } - ret->nopts = nopts; - ret->ndopts = ndopts; - ret->nodopts = nodopts; set_cadef_opts(ret); return all; @@ -1751,6 +1768,27 @@ ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp) return pp; } +/* Search for an option in all sets except the current one. + * Return true if found */ + +static int +ca_foreign_opt(Cadef curset, Cadef all, char *option) +{ + Cadef d; + Caopt p; + + for (d = all; d; d = d->snext) { + if (d == curset) + continue; + + for (p = d->opts; p; p = p->next) { + if (!strcmp(p->name, option)) + return 1; + } + } + return 0; +} + /* Return the n'th argument definition. */ static Caarg @@ -1776,77 +1814,95 @@ ca_get_arg(Cadef d, int n) * d: option definitions for a set * pass either: * xor: a list if exclusions - * opts: if set, all options excluded leaving only nornal/rest arguments - * if ca_xor list initialised, exclusions are added to it */ - -static LinkList ca_xor; + * opts: if set, all options excluded leaving only nornal/rest arguments */ -static int -ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname) +static void +ca_inactive(Cadef d, char **xor, int cur, int opts) { if ((xor || opts) && cur <= compcurrent) { Caopt opt; char *x; - int sl = (d->set ? (int)strlen(d->set) : -1), set = 0; + /* current word could be a prefix of a longer one so only do + * exclusions for single-letter options (for option clumping) */ + int single = (cur == compcurrent); for (; (x = (opts ? "-" : *xor)); xor++) { - if (optname && optname[0] == x[0] && strcmp(optname, x)) - continue; - if (ca_xor) - addlinknode(ca_xor, x); - set = 0; - if (sl > 0) { - if (strpfx(d->set, x)) { - x += sl; - set = 1; - } else if (!strncmp(d->set, x, sl - 1)) { - Caopt p; - - for (p = d->opts; p; p = p->next) - if (p->set) - p->active = 0; - - x = ":"; - set = 1; + int excludeall = 0; + char *grp = NULL; + size_t grplen; + char *next, *sep = x; + + while (*sep != '+' && *sep != '-' && *sep != ':' && *sep != '*' && !idigit(*sep)) { + if (!(next = strchr(sep, '-')) || !*++next) { + /* exclusion is just the name of a set or group */ + excludeall = 1; /* excluding options and args */ + sep += strlen(sep); + /* A trailing '-' is included in the various gsname fields but is not + * there for this branch. This is why we add excludeall to grplen + * when checking for the null in a few places below */ + break; } + sep = next; + } + if (sep > x) { /* exclusion included a set or group name */ + grp = x; + grplen = sep - grp; + x = sep; } - if (x[0] == ':' && !x[1]) { - if (set) { + + if (excludeall || (x[0] == ':' && !x[1])) { + if (grp) { Caarg a; for (a = d->args; a; a = a->next) - if (a->set) + if (a->gsname && !strncmp(a->gsname, grp, grplen) && + !a->gsname[grplen + excludeall]) a->active = 0; - if (d->rest && (!set || d->rest->set)) + if (d->rest && d->rest->gsname && + !strncmp(d->rest->gsname, grp, grplen) && + !d->rest->gsname[grplen + excludeall]) d->rest->active = 0; } else d->argsactive = 0; - } else if (x[0] == '-' && !x[1]) { + } + + if (excludeall || (x[0] == '-' && !x[1])) { Caopt p; for (p = d->opts; p; p = p->next) - if (!set || p->set) + if ((!grp || (p->gsname && !strncmp(p->gsname, grp, grplen) && + !p->gsname[grplen + excludeall])) && + !(single && *p->name && p->name[1] && p->name[2])) p->active = 0; - } else if (x[0] == '*' && !x[1]) { - if (d->rest && (!set || d->rest->set)) - d->rest->active = 0; - } else if (idigit(x[0])) { - int n = atoi(x); - Caarg a = d->args; - - while (a && a->num < n) - a = a->next; + } - if (a && a->num == n && (!set || a->set)) - a->active = 0; - } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set)) - opt->active = 0; + if (excludeall || (x[0] == '*' && !x[1])) { + if (d->rest && (!grp || (d->rest->gsname && + !strncmp(d->rest->gsname, grp, grplen) && + !d->rest->gsname[grplen + excludeall]))) + d->rest->active = 0; + } - if (opts) - break; + if (!excludeall) { + if (idigit(x[0])) { + int n = atoi(x); + Caarg a = d->args; + + while (a && a->num < n) + a = a->next; + + if (a && a->num == n && (!grp || (a->gsname && + !strncmp(a->gsname, grp, grplen)))) + a->active = 0; + } else if ((opt = ca_get_opt(d, x, 1, NULL)) && + (!grp || (opt->gsname && !strncmp(opt->gsname, grp, grplen))) && + !(single && *opt->name && opt->name[1] && opt->name[2])) + opt->active = 0; + if (opts) + break; + } } } - return 0; } /* State when parsing a command line. */ @@ -1875,7 +1931,6 @@ struct castate { int curpos; /* current word position */ int argend; /* total number of words */ int inopt; /* set to current word pos if word is a recognised option */ - int inrest; /* unused */ int inarg; /* in a normal argument */ int nth; /* number of current normal arg */ int doff; /* length of current option */ @@ -1934,7 +1989,7 @@ ca_opt_arg(Caopt opt, char *line) * existing options on the line. */ static int -ca_parse_line(Cadef d, int multi, int first) +ca_parse_line(Cadef d, Cadef all, int multi, int first) { Caarg adef, ddef; Caopt ptr, wasopt = NULL, dopt; @@ -1978,7 +2033,7 @@ ca_parse_line(Cadef d, int multi, int first) state.argbeg = state.optbeg = state.nargbeg = state.restbeg = state.actopts = state.nth = state.inopt = state.inarg = state.opt = state.arg = 1; state.argend = argend = arrlen(compwords) - 1; - state.inrest = state.doff = state.singles = state.oopt = 0; + state.doff = state.singles = state.oopt = 0; state.curpos = compcurrent; state.args = znewlinklist(); state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList)); @@ -2025,10 +2080,9 @@ ca_parse_line(Cadef d, int multi, int first) remnulargs(line); untokenize(line); - if (ca_inactive(d, argxor, cur, 0, NULL) || - ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--"))) { - if (ca_inactive(d, NULL, cur, 1, NULL)) - return 1; + ca_inactive(d, argxor, cur, 0); + if ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--")) { + ca_inactive(d, NULL, cur, 1); continue; } @@ -2104,9 +2158,7 @@ ca_parse_line(Cadef d, int multi, int first) if (!state.oargs[state.curopt->num]) state.oargs[state.curopt->num] = znewlinklist(); - if (ca_inactive(d, state.curopt->xor, cur, 0, - (cur == compcurrent ? state.curopt->name : NULL))) - return 1; + ca_inactive(d, state.curopt->xor, cur, 0); /* Collect the argument strings. Maybe. */ @@ -2159,9 +2211,7 @@ ca_parse_line(Cadef d, int multi, int first) if (!state.oargs[tmpopt->num]) state.oargs[tmpopt->num] = znewlinklist(); - if (ca_inactive(d, tmpopt->xor, cur, 0, - (cur == compcurrent ? tmpopt->name : NULL))) - return 1; + ca_inactive(d, tmpopt->xor, cur, 0); } } if (state.def && @@ -2183,20 +2233,13 @@ ca_parse_line(Cadef d, int multi, int first) else state.curopt = NULL; } else if (multi && (*line == '-' || *line == '+') && cur != compcurrent -#if 0 - /**** Ouch. Using this will disable the mutual exclusion - of different sets. Not using it will make the -A - pattern be effectively ignored with multiple sets. */ - && (!napat || !pattry(napat, line)) -#endif - ) + && (ca_foreign_opt(d, all, line))) return 1; else if (state.arg && (!napat || cur <= compcurrent || !pattry(napat, line))) { /* Otherwise it's a normal argument. */ - if (napat && cur <= compcurrent && - ca_inactive(d, NULL, cur + 1, 1, NULL)) - return 1; + if (napat && cur <= compcurrent) + ca_inactive(d, NULL, cur + 1, 1); arglast = 1; /* if this is the first normal arg after an option, may have been @@ -2231,7 +2274,6 @@ ca_parse_line(Cadef d, int multi, int first) if (ca_laststate.def) break; - state.inrest = 0; state.opt = (cur == state.nargbeg + 1 && (!multi || !*line || *line == '-' || *line == '+')); @@ -2421,19 +2463,19 @@ ca_set_data(LinkList descr, LinkList act, LinkList subc, restrict_range(ca_laststate.argbeg, ca_laststate.argend); } if (arg->opt) { - buf = (char *) zhalloc((arg->set ? strlen(arg->set) : 0) + + buf = (char *) zhalloc((arg->gsname ? strlen(arg->gsname) : 0) + strlen(arg->opt) + 40); if (arg->num > 0 && arg->type < CAA_REST) sprintf(buf, "%soption%s-%d", - (arg->set ? arg->set : ""), arg->opt, arg->num); + (arg->gsname ? arg->gsname : ""), arg->opt, arg->num); else sprintf(buf, "%soption%s-rest", - (arg->set ? arg->set : ""), arg->opt); + (arg->gsname ? arg->gsname : ""), arg->opt); } else if (arg->num > 0) { sprintf(nbuf, "argument-%d", arg->num); - buf = (arg->set ? dyncat(arg->set, nbuf) : dupstring(nbuf)); + buf = (arg->gsname ? dyncat(arg->gsname, nbuf) : dupstring(nbuf)); } else - buf = (arg->set ? dyncat(arg->set, "argument-rest") : + buf = (arg->gsname ? dyncat(arg->gsname, "argument-rest") : dupstring("argument-rest")); addlinknode(subc, buf); @@ -2537,47 +2579,29 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) * auto-description string, the optional -s, -S, -A and -M options * given to _arguments and the specs. */ if (compcurrent > 1 && compwords[0]) { - Cadef def; + Cadef def, all; int cap = ca_parsed, multi, first = 1, use, ret = 0; - LinkList cax = ca_xor, nx; - LinkNode node; Castate states = NULL, sp; - char *xor[2]; ca_parsed = 0; - xor[1] = NULL; - if (!(def = get_cadef(nam, args + 1))) + if (!(def = all = get_cadef(nam, args + 1))) return 1; multi = !!def->snext; /* if we have sets */ ca_parsed = cap; - ca_xor = (multi ? newlinklist() : NULL); while (def) { /* for each set */ - use = !ca_parse_line(def, multi, first); - nx = ca_xor; - ca_xor = NULL; /* don't want to duplicate the xors in the list */ - while ((def = def->snext)) { - if (nx) { - for (node = firstnode(nx); node; incnode(node)) { - xor[0] = (char *) getdata(node); - if (!strcmp(xor[0], def->sname) || - ca_inactive(def, xor, compcurrent, 0, NULL)) - break; /* exclude this whole set */ - } - if (!node) /* continue with this set */ - break; - } - /* entire set was excluded, continue to next set */ - } - ca_xor = nx; + use = !ca_parse_line(def, all, multi, first); + def = def->snext; if (use && def) { + /* entry needed so save it into list */ sp = (Castate) zalloc(sizeof(*sp)); memcpy(sp, &ca_laststate, sizeof(*sp)); sp->snext = states; states = sp; } else if (!use && !def) { + /* final entry not needed */ if (states) { freecastate(&ca_laststate); memcpy(&ca_laststate, states, sizeof(*sp)); @@ -2589,7 +2613,6 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } first = 0; } - ca_xor = cax; ca_parsed = 1; ca_laststate.snext = states; @@ -2602,7 +2625,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) * things _arguments has to execute at this place on the line (the * sub-contexts are used as tags). * The return value is particularly important here, it says if - * there are arguments to completely at all. */ + * there are arguments to complete at all. */ { LinkList descr, act, subc; Caarg arg; @@ -2805,7 +2828,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) for (s = lstate; s; s = s->snext) for (o = s->d->opts, a = s->oargs; o; o = o->next, a++) if (*a) { - *p++ = (o->set ? tricat(o->set, o->name, "") : + *p++ = (o->gsname ? tricat(o->gsname, o->name, "") : ztrdup(o->name)); *p++ = ca_colonlist(*a); } @@ -3546,8 +3569,8 @@ bin_compvalues(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) Cvval val = cv_get_val(cv_laststate.d, args[1]); if (val && val->arg) { - setsparam(args[2], val->arg->descr); - setsparam(args[3], val->arg->action); + setsparam(args[2], ztrdup(val->arg->descr)); + setsparam(args[3], ztrdup(val->arg->action)); if (args[4]) setsparam(args[4], ztrdup(val->name)); @@ -3905,6 +3928,8 @@ bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) if (*q) { char *qq, *qqq; + queue_signals(); + if (c) *c = '\0'; @@ -3976,6 +4001,8 @@ bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } if (c) *c = ':'; + + unqueue_signals(); } } if (num) { @@ -4438,17 +4465,24 @@ cfp_matcher_pats(char *matcher, char *add) if (m && m != pcm_err) { char *tmp; int al = strlen(add), zl = ztrlen(add), tl, cl; - VARARR(Cmatcher, ms, zl); + VARARR(Cmatcher, ms, zl); /* One Cmatcher per character */ Cmatcher *mp; Cpattern stopp; int stopl = 0; + /* zl >= (number of wide characters) is guaranteed */ memset(ms, 0, zl * sizeof(Cmatcher)); for (; m && *add; m = m->next) { stopp = NULL; if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) { if (m->llen == 1 && m->wlen == 1) { + /* + * In this loop and similar loops below we step + * through tmp one (possibly wide) character at a + * time. pattern_match() compares only the first + * character using unmeta_one() so keep in step. + */ for (tmp = add, tl = al, mp = ms; tl; ) { if (pattern_match(m->line, tmp, NULL, NULL)) { if (*mp) { @@ -4458,10 +4492,10 @@ cfp_matcher_pats(char *matcher, char *add) } else *mp = m; } - cl = (*tmp == Meta) ? 2 : 1; + (void) unmeta_one(tmp, &cl); tl -= cl; tmp += cl; - mp += cl; + mp++; } } else { stopp = m->line; @@ -4478,10 +4512,10 @@ cfp_matcher_pats(char *matcher, char *add) } else *mp = m; } - cl = (*tmp == Meta) ? 2 : 1; + (void) unmeta_one(tmp, &cl); tl -= cl; tmp += cl; - mp += cl; + mp++; } } else if (m->llen) { stopp = m->line; @@ -4504,7 +4538,7 @@ cfp_matcher_pats(char *matcher, char *add) al = tmp - add; break; } - cl = (*tmp == Meta) ? 2 : 1; + (void) unmeta_one(tmp, &cl); tl -= cl; tmp += cl; } @@ -4685,6 +4719,8 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, if (!*p) continue; + queue_signals(); /* Protect PAT_STATIC */ + tokenize(f); pprog = patcompile(f, PAT_STATIC, NULL); untokenize(f); @@ -4717,6 +4753,8 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, } } } + + unqueue_signals(); } } } diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c index 3db0781ff..bf83906f2 100644 --- a/Src/Zle/textobjects.c +++ b/Src/Zle/textobjects.c @@ -48,9 +48,10 @@ int selectword(UNUSED(char **args)) { int n = zmult; - int all = (bindk == t_selectaword || bindk == t_selectablankword); - int (*viclass)(ZLE_CHAR_T) = (bindk == t_selectaword || - bindk == t_selectinword) ? wordclass : blankwordclass; + int all = IS_THINGY(bindk, selectaword) || + IS_THINGY(bindk, selectablankword); + int (*viclass)(ZLE_CHAR_T) = (IS_THINGY(bindk, selectaword) || + IS_THINGY(bindk, selectinword)) ? wordclass : blankwordclass; int sclass = viclass(zleline[zlecs]); int doblanks = all && sclass; @@ -288,7 +289,7 @@ selectargument(UNUSED(char **args)) free(stringaszleline(linein, wstarts[wcur], &zlecs, &tmpsz, &mark)); free(linein); - if (bindk == t_selectinshellword) { + if (IS_THINGY(bindk, selectinshellword)) { ZLE_CHAR_T *match = ZWS("`\'\""); ZLE_CHAR_T *lmatch = ZWS("\'({"), *rmatch = ZWS("\')}"); ZLE_CHAR_T *ematch = match, *found; diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 8f92e5611..07b310180 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -230,6 +230,13 @@ struct thingy { /* DISABLED is (1<<0) */ #define TH_IMMORTAL (1<<1) /* can't refer to a different widget */ +/* + * Check if bindk refers to named thingy (a set of bare characters), + * also checking the special .thingy widget. + */ +#define IS_THINGY(bindk, name) \ + ((bindk) == t_ ## name || (bindk) == t_D ## name) + /* command modifier prefixes */ struct modifier { diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index abd6e1749..581ca4979 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -1220,13 +1220,14 @@ doisearch(char **args, int dir, int pattern) char *patbuf = ztrdup(sbuf); char *patstring; /* - * Use static pattern buffer since we don't need - * to maintain it and won't call other pattern functions - * meanwhile. - * Use PAT_NOANCH because we don't need the match - * anchored to the end, even if it is at the start. + * Do not use static pattern buffer (PAT_STATIC) since we + * call zle hooks, which might call other pattern + * functions. Use PAT_ZDUP because we re-use the pattern + * in subsequent loops, so we can't pushheap/popheap. + * Use PAT_NOANCH because we don't need the match anchored + * to the end, even if it is at the start. */ - int patflags = PAT_STATIC|PAT_NOANCH; + int patflags = PAT_ZDUP|PAT_NOANCH; if (sbuf[0] == '^') { /* * We'll handle the anchor later when @@ -1521,6 +1522,7 @@ doisearch(char **args, int dir, int pattern) if (only_one || !top_spot || old_sbptr != sbptr) break; } + freepatprog(patprog); patprog = NULL; nosearch = 1; skip_pos = 0; @@ -1632,6 +1634,7 @@ doisearch(char **args, int dir, int pattern) } strcpy(sbuf + sbptr, paste); sbptr += pastelen; + freepatprog(patprog); patprog = NULL; free(paste); } else if (cmd == Th(z_acceptsearch)) { @@ -1682,6 +1685,7 @@ doisearch(char **args, int dir, int pattern) * always valid at this point. */ sbptr += zlecharasstring(LASTFULLCHAR, sbuf + sbptr); + freepatprog(patprog); patprog = NULL; } if (feep) @@ -1702,6 +1706,7 @@ doisearch(char **args, int dir, int pattern) zsfree(okeymap); if (matchlist) freematchlist(matchlist); + freepatprog(patprog); isearch_active = 0; /* * Don't allow unused characters provided as a string to the diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 04eb70675..2e96ac780 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -961,7 +961,7 @@ bin_bindkey_meta(char *name, char *kmname, Keymap km, UNUSED(char **argv), UNUSE m[0] = i; metafy(m, 1, META_NOALLOC); fn = keybind(km, m, &str); - if(fn == t_selfinsert || fn == t_undefinedkey) + if(IS_THINGY(fn, selfinsert) || fn == t_undefinedkey) bindkey(km, m, refthingy(Th(metabind[i - 128])), NULL); } return 0; diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 15ea79643..be2b062b0 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1245,6 +1245,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) resetneeded = 0; fetchttyinfo = 0; trashedzle = 0; + clearflag = 0; raw_lp = lp; lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL, &pmpt_attr); raw_rp = rp; @@ -1484,6 +1485,13 @@ execzlefunc(Thingy func, char **args, int set_bindk) int inuse = w->flags & WIDGET_INUSE; w->flags |= WIDGET_INUSE; + if (osi > 0) { + /* + * Many commands don't like having a closed stdin, open on + * /dev/null instead + */ + open("/dev/null", O_RDWR | O_NOCTTY); /* ignore failure */ + } if (*args) { largs = newlinklist(); addlinknode(largs, dupstring(w->u.fnnam)); diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 1e4c5b832..0a922d2d6 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -85,6 +85,8 @@ static const struct gsu_integer cursor_gsu = { get_cursor, set_cursor, zleunsetfn }; static const struct gsu_integer histno_gsu = { get_histno, set_histno, zleunsetfn }; +static const struct gsu_integer keys_queued_count_gsu = +{ get_keys_queued_count, NULL, zleunsetfn }; static const struct gsu_integer mark_gsu = { get_mark, set_mark, zleunsetfn }; static const struct gsu_integer numeric_gsu = @@ -146,6 +148,8 @@ static struct zleparam { { "HISTNO", PM_INTEGER, GSU(histno_gsu), NULL }, { "KEYMAP", PM_SCALAR | PM_READONLY, GSU(keymap_gsu), NULL }, { "KEYS", PM_SCALAR | PM_READONLY, GSU(keys_gsu), NULL }, + { "KEYS_QUEUED_COUNT", PM_INTEGER | PM_READONLY, GSU(keys_queued_count_gsu), + NULL}, { "killring", PM_ARRAY, GSU(killring_gsu), NULL }, { "LASTABORTEDSEARCH", PM_SCALAR | PM_READONLY, GSU(lastabortedsearch_gsu), NULL }, @@ -458,6 +462,13 @@ get_keys(UNUSED(Param pm)) } /**/ +static zlong +get_keys_queued_count(UNUSED(Param pm)) +{ + return kungetct; +} + +/**/ static void set_numeric(UNUSED(Param pm), zlong x) { diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 8d173cda1..d0dd1ef06 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -1278,7 +1278,7 @@ zrefresh(void) #ifdef __STDC_ISO_10646__ !ZSH_INVALID_WCHAR_TEST(*t) && #endif - iswprint(*t) && (width = WCWIDTH(*t)) > 0) { + WC_ISPRINT(*t) && (width = WCWIDTH(*t)) > 0) { int ichars; if (width > rpms.sen - rpms.s) { int started = 0; @@ -1460,7 +1460,7 @@ zrefresh(void) u = outputline; for (; u < outputline + outll; u++) { #ifdef MULTIBYTE_SUPPORT - if (iswprint(*u)) { + if (WC_ISPRINT(*u)) { int width = WCWIDTH(*u); /* Handle wide characters as above */ if (width > rpms.sen - rpms.s) { @@ -2434,8 +2434,8 @@ redisplay(UNUSED(char **args)) moveto(0, 0); zputc(&zr_cr); /* extra care */ tc_upcurs(lprompth - 1); - resetneeded = !showinglist; - clearflag = showinglist; + resetneeded = 1; + clearflag = 0; return 0; } @@ -2468,7 +2468,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) if (tmpline[t0] == ZWC('\t')) vsiz = (vsiz | 7) + 2; #ifdef MULTIBYTE_SUPPORT - else if (iswprint(tmpline[t0]) && ((width = WCWIDTH(tmpline[t0])) > 0)) { + else if (WC_ISPRINT(tmpline[t0]) && ((width = WCWIDTH(tmpline[t0])) > 0)) { vsiz += width; if (isset(COMBININGCHARS) && IS_BASECHAR(tmpline[t0])) { while (t0 < tmpll-1 && IS_COMBINING(tmpline[t0+1])) @@ -2556,7 +2556,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) vp->atr = all_atr_on | all_atr_off; vp++; #ifdef MULTIBYTE_SUPPORT - } else if (iswprint(tmpline[t0]) && + } else if (WC_ISPRINT(tmpline[t0]) && (width = WCWIDTH(tmpline[t0])) > 0) { int ichars; if (isset(COMBININGCHARS) && IS_BASECHAR(tmpline[t0])) { diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index c7092854a..f7e9829c2 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -602,7 +602,7 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func) Thingy t; Widget w, cw; - if (require_module("zsh/complete", NULL) == 1) { + if (require_module("zsh/complete", NULL, 0) == 1) { zwarnnam(name, "can't load complete module"); return 1; } @@ -703,7 +703,7 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { Thingy t; struct modifier modsave = zmod; - int ret, saveflag = 0, setbindk = 0; + int ret, saveflag = 0, setbindk = 0, remetafy; char *wname = *args++, *keymap_restore = NULL, *keymap_tmp; if (!wname) @@ -714,7 +714,15 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) return 1; } - UNMETACHECK(); + /* + * zle is callable in traps, so we can't be sure the line is + * in its normal state. + */ + if (zlemetaline) { + unmetafy_line(); + remetafy = 1; + } else + remetafy = 0; while (*args && **args == '-') { char *num; @@ -728,6 +736,8 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) num = args[0][1] ? args[0]+1 : args[1]; if (!num) { zwarnnam(name, "number expected after -%c", **args); + if (remetafy) + metafy_line(); return 1; } if (!args[0][1]) @@ -745,19 +755,26 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) keymap_tmp = args[0][1] ? args[0]+1 : args[1]; if (!keymap_tmp) { zwarnnam(name, "keymap expected after -%c", **args); + if (remetafy) + metafy_line(); return 1; } if (!args[0][1]) *++args = "" - 1; keymap_restore = dupstring(curkeymapname); - if (selectkeymap(keymap_tmp, 0)) + if (selectkeymap(keymap_tmp, 0)) { + if (remetafy) + metafy_line(); return 1; + } break; case 'w': setbindk = 1; break; default: zwarnnam(name, "unknown option: %s", *args); + if (remetafy) + metafy_line(); return 1; } } @@ -775,6 +792,8 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) zmod = modsave; if (keymap_restore) selectkeymap(keymap_restore, 0); + if (remetafy) + metafy_line(); return ret; } diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 3d8679119..5a9cccb6f 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -2407,53 +2407,6 @@ sfxlen(char *s, char *t) } #endif -/* This is zstrcmp with ignoring backslashes. */ - -/**/ -mod_export int -zstrbcmp(const char *a, const char *b) -{ - const char *astart = a; - - while (*a && *b) { - if (*a == '\\') - a++; - if (*b == '\\') - b++; - if (*a != *b || !*a) - break; - a++; - b++; - } - if (isset(NUMERICGLOBSORT) && (idigit(*a) || idigit(*b))) { - for (; a > astart && idigit(a[-1]); a--, b--); - if (idigit(*a) && idigit(*b)) { - while (*a == '0') - a++; - while (*b == '0') - b++; - for (; idigit(*a) && *a == *b; a++, b++); - if (idigit(*a) || idigit(*b)) { - int cmp = (int) STOUC(*a) - (int) STOUC(*b); - - while (idigit(*a) && idigit(*b)) - a++, b++; - if (idigit(*a) && !idigit(*b)) - return 1; - if (idigit(*b) && !idigit(*a)) - return -1; - - return cmp; - } - } - } -#ifndef HAVE_STRCOLL - return (int)(*a - *b); -#else - return strcoll(a,b); -#endif -} - /* This is used to print the strings (e.g. explanations). * * It returns the number of lines printed. */ |