diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 10 | ||||
-rw-r--r-- | Src/Zle/comp1.c | 79 | ||||
-rw-r--r-- | Src/Zle/comp1.export | 2 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 52 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 9 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 60 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 47 | ||||
-rw-r--r-- | Src/Zle/zle_thingy.c | 4 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 347 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 4 |
10 files changed, 423 insertions, 191 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 20e3d2cce..5f263557a 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -210,6 +210,7 @@ struct cmatch { int flags; /* see CMF_* below */ int brpl; /* the place where to put the brace prefix */ int brsl; /* ...and the suffix */ + char *rems; /* when to remove the suffix */ }; #define CMF_FILE 1 /* this is a file */ @@ -272,3 +273,12 @@ struct cline { #define CFN_FIRST 1 #define CFN_DEFAULT 2 + +/* Flags for compadd and addmatches(). */ + +#define CAF_QUOTE 1 +#define CAF_MENU 2 +#define CAF_NOSORT 4 +#define CAF_ALT 8 +#define CAF_FIGNORE 16 +#define CAF_MATCH 32 diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index 36588a385..a5e35bc3c 100644 --- a/Src/Zle/comp1.c +++ b/Src/Zle/comp1.c @@ -49,7 +49,7 @@ void (*makecompparamsptr) _((void)); /* pointers to functions required by compctl and defined by zle */ /**/ -void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, int, int, int, int, int, char **)); +void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **)); /**/ char *(*comp_strptr) _((int*,int*)); @@ -95,7 +95,8 @@ int incompfunc; /**/ long compcurrent, - compnmatches; + compnmatches, + compmatcher; /**/ char *compcontext, @@ -104,14 +105,8 @@ char *compcontext, *compsuffix, *compiprefix; -/* This variable and the functions rembslash() and quotename() came from * - * zle_tricky.c, but are now used in compctl.c, too. */ - -/* 1 if we are completing in a string */ - -/**/ -int instring; - +/* The function rembslash() came from zle_tricky.c, but is now used * + * in compctl.c, too. */ /**/ static void @@ -395,70 +390,6 @@ rembslash(char *s) return t; } -/* Quote the string s and return the result. If e is non-zero, the * - * pointer it points to may point to a position in s and in e the position * - * of the corresponding character in the quoted string is returned. Like * - * e, te may point to a position in the string and pl is used to return * - * the position of the character pointed to by te in the quoted string. * - * The string is metafied and may contain tokens. */ - -/**/ -char * -quotename(const char *s, char **e, char *te, int *pl) -{ - const char *u, *tt; - char *v, buf[PATH_MAX * 2]; - int sf = 0; - - tt = v = buf; - u = s; - for (; *u; u++) { - if (e && *e == u) - *e = v, sf |= 1; - if (te == u) - *pl = v - tt, sf |= 2; - if (ispecial(*u) && - (!instring || (isset(BANGHIST) && - *u == (char)bangchar) || - (instring == 2 && - (*u == '$' || *u == '`' || *u == '\"')) || - (instring == 1 && *u == '\''))) { - if (*u == '\n' || (instring == 1 && *u == '\'')) { - if (unset(RCQUOTES)) { - *v++ = '\''; - if (*u == '\'') - *v++ = '\\'; - *v++ = *u; - *v++ = '\''; - } else if (*u == '\n') - *v++ = '"', *v++ = '\n', *v++ = '"'; - else - *v++ = '\'', *v++ = '\''; - continue; - } else - *v++ = '\\'; - } - if(*u == Meta) - *v++ = *u++; - *v++ = *u; - } - *v = '\0'; - if (strcmp(buf, s)) - tt = dupstring(buf); - else - tt = s; - v += tt - buf; - if (e && (sf & 1)) - *e += tt - buf; - - if (e && *e == u) - *e = v; - if (te == u) - *pl = v - tt; - - return (char *) tt; -} - /**/ int setup_comp1(Module m) diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export index 72581173b..278006b6a 100644 --- a/Src/Zle/comp1.export +++ b/Src/Zle/comp1.export @@ -14,6 +14,7 @@ compcontext compctltab compcurrent compiprefix +compmatcher compnmatches compprefix comp_strptr @@ -30,5 +31,4 @@ makecomplistcallptr makecomplistctlptr makecompparamsptr patcomps -quotename rembslash diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 879042cf3..dcc206c96 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1385,7 +1385,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) untokenize(p); quotedzputs(p, stdout); } else - quotedzputs(quotename(s, NULL, NULL, NULL), stdout); + quotedzputs(bslashquote(s, NULL, NULL, NULL, 0), stdout); } /* loop through flags w/o args that are set, printing them if so */ @@ -1515,7 +1515,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) char *p = dupstring(s); untokenize(p); - quotedzputs(quotename(p, NULL, NULL, NULL), stdout); + quotedzputs(bslashquote(p, NULL, NULL, NULL, 0), stdout); } } putchar('\n'); @@ -1547,8 +1547,6 @@ bin_compctl(char *name, char **argv, char *ops, int func) cclist = 0; showmask = 0; - instring = 0; - /* Parse all the arguments */ if (*argv) { /* Let's see if this is a global matcher definition. */ @@ -1671,8 +1669,9 @@ bin_compadd(char *name, char **argv, char *ops, int func) { char *p, **sp, *e; char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL; - char *pre = NULL, *suf = NULL, *group = NULL; - int f = 0, q = 0, m = 0, ns = 0, a = 0; + char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL; + int f = 0, a = 0, dm; + Cmatcher match = NULL; if (incompfunc != 1) { zerrnam(name, "can only be called from completion function", NULL, 0); @@ -1681,21 +1680,25 @@ bin_compadd(char *name, char **argv, char *ops, int func) for (; *argv && **argv == '-'; argv++) { for (p = *argv + 1; *p; p++) { sp = NULL; + dm = 0; switch (*p) { case 'q': f |= CMF_REMOVE; break; case 'Q': - q = 1; + a |= CAF_QUOTE; break; case 'f': f |= CMF_FILE; break; + case 'F': + a |= CAF_FIGNORE; + break; case 'n': f |= CMF_NOLIST; break; case 'U': - m = 1; + a |= CAF_MENU; break; case 'P': sp = ⪯ @@ -1711,7 +1714,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) break; case 'V': if (!group) - ns = 1; + a |= CAF_NOSORT; sp = &group; e = "group name expected after -%c"; break; @@ -1732,7 +1735,19 @@ bin_compadd(char *name, char **argv, char *ops, int func) e = "string expected after -%c"; break; case 'a': - a = 1; + a |= CAF_ALT; + break; + case 'm': + a |= CAF_MATCH; + break; + case 'M': + sp = &m; + e = "matching specification expected after -%c"; + dm = 1; + break; + case 'r': + sp = &rs; + e = "string expected after -%c"; break; case '-': argv++; @@ -1756,6 +1771,10 @@ bin_compadd(char *name, char **argv, char *ops, int func) zerrnam(name, e, NULL, *p); return 1; } + if (dm && (match = parse_cmatcher(name, m)) == pcm_err) { + match = NULL; + return 1; + } } } } @@ -1764,7 +1783,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) return 1; addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group, - f, q, m, ns, a, argv); + rs, f, a, match, argv); return 0; } @@ -1794,6 +1813,7 @@ static struct compparam { { "SUFFIX", PM_SCALAR, VAR(compsuffix) }, { "IPREFIX", PM_SCALAR, VAR(compiprefix) }, { "NMATCHES", PM_INTEGER, VAR(compnmatches) }, + { "MATCHER", PM_INTEGER, VAR(compmatcher) }, { NULL, 0, NULL } }; @@ -2096,6 +2116,15 @@ cond_nmatches(char **a, int id) return 0; } +/**/ +static int +cond_matcher(char **a, int id) +{ + if (comp_check()) + return compmatcher == cond_val(a, 0); + return 0; +} + static struct builtin bintab[] = { BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL), BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL), @@ -2119,6 +2148,7 @@ static struct conddef cotab[] = { CONDDEF("after", 0, cond_range, 1, 1, 0), CONDDEF("mafter", 0, cond_range, 1, 1, 1), CONDDEF("nmatches", 0, cond_nmatches, 1, 1, 0), + CONDDEF("matcher", 0, cond_matcher, 1, 1, 0), }; static struct funcwrap wrapper[] = { diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index fda204222..e6b385652 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -663,6 +663,11 @@ doisearch(int dir) static char *previous_search = NULL; static int previous_search_len = 0; + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; + strcpy(ibuf, ISEARCH_PROMPT); memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); remember_edits(); @@ -943,6 +948,10 @@ getvisrchstr(void) zsfree(visrchstr); visrchstr = NULL; } + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; statusline = sbuf; sbuf[0] = (visrchsense == -1) ? '?' : '/'; selectkeymap("main", 1); diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 03549b5d0..ca7a7fe19 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -661,10 +661,17 @@ bin_vared(char *name, char **args, char *ops, int func) { char *s; char *t; - Param pm; + Value v; + Param pm = 0; int create = 0; + int type = PM_SCALAR; char *p1 = NULL, *p2 = NULL; + if (zleactive) { + zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0); + return 1; + } + /* all options are handled as arguments */ while (*args && **args == '-') { while (*++(*args)) @@ -674,6 +681,12 @@ bin_vared(char *name, char **args, char *ops, int func) yet exist */ create = 1; break; + case 'a': + type = PM_ARRAY; + break; + case 'A': + type = PM_HASHED; + break; case 'p': /* -p option -- set main prompt string */ if ((*args)[1]) @@ -709,6 +722,9 @@ bin_vared(char *name, char **args, char *ops, int func) } args++; } + if (type && !create) { + zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A", 0); + } /* check we have a parameter name */ if (!*args) { @@ -716,17 +732,17 @@ bin_vared(char *name, char **args, char *ops, int func) return 1; } /* handle non-existent parameter */ - if (!(s = getsparam(args[0]))) { - if (create) - createparam(args[0], PM_SCALAR); - else { - zwarnnam(name, "no such variable: %s", args[0], 0); - return 1; - } - } - - if(zleactive) { - zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0); + s = args[0]; + v = fetchvalue(&s, (!create || type == PM_SCALAR), + SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY); + if (!v && !create) { + zwarnnam(name, "no such variable: %s", args[0], 0); + return 1; + } else if (v) { + s = getstrvalue(v); + pm = v->pm; + } else if (*s) { + zwarnnam(name, "invalid parameter name: %s", args[0], 0); return 1; } @@ -744,14 +760,24 @@ bin_vared(char *name, char **args, char *ops, int func) if (t[strlen(t) - 1] == '\n') t[strlen(t) - 1] = '\0'; /* final assignment of parameter value */ - pm = (Param) paramtab->getnode(paramtab, args[0]); - if (pm && PM_TYPE(pm->flags) == PM_ARRAY) { + if (create && (!pm || (type && PM_TYPE(pm->flags) != type))) { + if (pm) + unsetparam(args[0]); + createparam(args[0], type); + pm = 0; + } + if (!pm) + pm = (Param) paramtab->getnode(paramtab, args[0]); + if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) { char **a; PERMALLOC { a = spacesplit(t, 1); } LASTALLOC; - setaparam(args[0], a); + if (PM_TYPE(pm->flags) == PM_ARRAY) + setaparam(args[0], a); + else + sethparam(args[0], a); } else setsparam(args[0], t); return 0; @@ -766,6 +792,10 @@ describekeybriefly(void) if (statusline) return; + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; statusline = "Describe key briefly: _"; statusll = strlen(statusline); zrefresh(); diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 836ff09ae..4b5df9cde 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -612,6 +612,10 @@ executenamedcommand(char *prmt) char *ptr; char *okeymap = curkeymapname; + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; cmdbuf = halloc(l + NAMLEN + 2); strcpy(cmdbuf, prmt); statusline = cmdbuf; @@ -792,6 +796,49 @@ makeparamsuffix(int br, int n) } } +/* Set up suffix given a string containing the characters on which to * + * remove the suffix. */ + +/**/ +void +makesuffixstr(char *s, int n) +{ + if (s) { + int inv, i, v, z = 0; + + if (*s == '^' || *s == '!') { + inv = 1; + s++; + } else + inv = 0; + s = getkeystring(s, &i, 5, &z); + s = metafy(s, i, META_USEHEAP); + + if (inv) { + v = 0; + for (i = 0; i < 257; i++) + suffixlen[i] = n; + } else + v = n; + + if (z) + suffixlen[256] = v; + + while (*s) { + if (s[1] == '-' && s[2]) { + int b = (int) *s, e = (int) s[2]; + + while (b <= e) + suffixlen[b++] = v; + s += 2; + } else + suffixlen[STOUC(*s)] = v; + s++; + } + } else + makesuffix(n); +} + /* Remove suffix, if there is one, when inserting character c. */ /**/ diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 629d5a84e..d055c45c1 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -390,7 +390,7 @@ scanlistwidgets(HashNode hn, int list) if(w->flags & WIDGET_INT) return; if(list) { - fputs("zle -N ", stdout); + printf("zle -%c ", (w->flags & WIDGET_NCOMP) ? 'C' : 'N'); if(t->nam[0] == '-') fputs("-- ", stdout); quotedzputs(t->nam, stdout); @@ -406,7 +406,7 @@ scanlistwidgets(HashNode hn, int list) } else { nicezputs(t->nam, stdout); if (w->flags & WIDGET_NCOMP) { - fputs(" -c ", stdout); + fputs(" -C ", stdout); nicezputs(w->u.comp.wid, stdout); fputc(' ', stdout); nicezputs(w->u.comp.func, stdout); diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index df3e11f46..f1285da8c 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -223,7 +223,7 @@ typedef struct aminfo *Aminfo; struct aminfo { int cpl, csl, icpl, icsl; /* common prefix/suffix lengths */ - int prerest; /* minimum prefix rest */ + int minlen; /* minimum match length */ int suflen; /* minimum suffix length */ Cmatch firstm; /* the first match */ char *pprefix; /* common part of the -P prefixes */ @@ -270,6 +270,19 @@ enum { COMP_COMPLETE, COMP_LIST_EXPAND }; #define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND) +/* Non-zero if the last completion done was ambiguous (used to find * + * out if AUTOMENU should start). More precisely, it's nonzero after * + * successfully doing any completion, unless the completion was * + * unambiguous and did not cause the display of a completion list. * + * From the other point of view, it's nonzero iff AUTOMENU (if set) * + * should kick in on another completion. * + * * + * If both AUTOMENU and BASHAUTOLIST are set, then we get a listing * + * on the second tab, a` la bash, and then automenu kicks in when * + * lastambig == 2. */ + +static int lastambig; + /**/ void completecall(void) @@ -287,8 +300,13 @@ completeword(void) useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) selfinsert(); - else - docomplete(COMP_COMPLETE); + else { + if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { + docomplete(COMP_LIST_COMPLETE); + lastambig = 2; + } else + docomplete(COMP_COMPLETE); + } } /**/ @@ -358,8 +376,13 @@ expandorcomplete(void) useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) selfinsert(); - else - docomplete(COMP_EXPAND_COMPLETE); + else { + if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { + docomplete(COMP_LIST_COMPLETE); + lastambig = 2; + } else + docomplete(COMP_EXPAND_COMPLETE); + } } /**/ @@ -451,15 +474,6 @@ static int lincmd, linredir; static char *rdstr; -/* Non-zero if the last completion done was ambiguous (used to find * - * out if AUTOMENU should start). More precisely, it's nonzero after * - * successfully doing any completion, unless the completion was * - * unambiguous and did not cause the display of a completion list. * - * From the other point of view, it's nonzero iff AUTOMENU (if set) * - * should kick in on another completion. */ - -static int lastambig; - /* This holds the name of the current command (used to find the right * * compctl). */ @@ -473,6 +487,16 @@ static char *varname; static int insubscr; +/* 1 if we are completing in a string */ + +/**/ +int instring; + +/* Convenience macro for calling bslashquote() (formerly quotename()). * + * This uses the instring variable above. */ + +#define quotename(s, e, te, pl) bslashquote(s, e, te, pl, instring) + /* Check if the given string is the name of a parameter and if this * * parameter is one worth expanding. */ @@ -569,7 +593,8 @@ docomplete(int lst) /* Check if we have to start a menu-completion (via automenu). */ - if ((amenu = (isset(AUTOMENU) && lastambig))) + if ((amenu = (isset(AUTOMENU) && lastambig && + (!isset(BASHAUTOLIST) || lastambig == 2)))) usemenu = 1; /* Expand history references before starting completion. If anything * @@ -919,7 +944,7 @@ unmetafy_line(void) static char * get_comp_string(void) { - int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins; + int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, inarr, ia, parct; char *s = NULL, *linptr, *tmp, *p, *tt = NULL; zsfree(brbeg); @@ -982,7 +1007,7 @@ get_comp_string(void) inpush(dupstrspace((char *) linptr), 0, NULL); strinbeg(); stophist = 2; - i = tt0 = cp = rd = ins = oins = 0; + i = tt0 = cp = rd = ins = oins = inarr = parct = ia = 0; /* This loop is possibly the wrong way to do this. It goes through * * the previously massaged command line using the lexer. It stores * @@ -1001,7 +1026,21 @@ get_comp_string(void) linredir = (inredir && !ins); oins = ins; /* Get the next token. */ + if (inarr) + incmdpos = 0; ctxtlex(); + if (tok == ENVARRAY) { + inarr = 1; + zsfree(varname); + varname = ztrdup(tokstr); + } else if (tok == INPAR) + parct++; + else if (tok == OUTPAR) { + if (parct) + parct--; + else + inarr = 0; + } if (inredir) rdstr = tokstrings[tok]; if (tok == DINPAR) @@ -1043,6 +1082,7 @@ get_comp_string(void) clwpos = i; cp = lincmd; rd = linredir; + ia = inarr; if (inwhat == IN_NOTHING && incond) inwhat = IN_COND; } else if (linredir) @@ -1084,8 +1124,13 @@ get_comp_string(void) zsfree(clwords[clwnum]); clwords[clwnum] = NULL; t0 = tt0; - lincmd = cp; - linredir = rd; + if (ia) { + lincmd = linredir = 0; + inwhat = IN_ENV; + } else { + lincmd = cp; + linredir = rd; + } strinend(); inpop(); errflag = zleparse = 0; @@ -1789,9 +1834,17 @@ inst_cline(Cline l, int pl, int sl) pl += brpl; i = cs - wb; + if (pl >= 0 && i >= pl && brbeg && *brbeg) { + inststrlen(brbeg, 1, -1); + pl = -1; + hb = 1; + } + if (sl >= 0 && i >= sl && brend && *brend) { + inststrlen(brend, 1, -1); + sl = -1; + hb = 1; + } while (l) { - if (d < 0 && (l->flags & CLF_DIFF)) - d = cs; if (m < 0 && (l->flags & (CLF_MISS | CLF_SUF)) == (CLF_MISS | CLF_SUF)) m = cs; if (l->flags & CLF_MID) { @@ -1805,6 +1858,8 @@ inst_cline(Cline l, int pl, int sl) } else { inststrlen(l->line, 1, l->llen); } + if (d < 0 && (l->flags & CLF_DIFF)) + d = cs; if (m < 0 && (l->flags & CLF_MISS)) m = cs; i += l->llen; @@ -1893,8 +1948,10 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp, while (ll && lw) { for (ms = mstack; ms; ms = ms->next) { for (mp = ms->matcher; mp; mp = mp->next) { - if (nm == mp || lm == mp) + if (nm == mp || lm == mp) { + nm = NULL; continue; + } t = 1; /* Try to match the prefix, if any. */ if (mp->flags & CMF_LEFT) { @@ -1930,7 +1987,7 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp, NULL, NULL, mp)) break; } - if (k) { + if (k && i) { if (nlp) { nw = addtoword(&rw, &rwlen, nw, mp, l, w, i, 0); @@ -2106,8 +2163,10 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm) while (ll && lw) { for (ms = mstack; ms; ms = ms->next) { for (mp = ms->matcher; mp; mp = mp->next) { - if (nm == mp || lm == mp) + if (nm == mp || lm == mp) { + nm = NULL; continue; + } t = 1; if (mp->flags & CMF_RIGHT) { if (il < mp->ralen || iw < mp->ralen) @@ -2135,13 +2194,13 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm) if (t) { int i = 0, j = iw, k = lw; int jj = il + mp->llen, kk = ll - mp->llen; - char *p = l - mp->llen, *q = w; + char *p = l - mp->llen - 1, *q = w - 1; for (; k; i++, j++, k--, q--) - if (match_sfx(p, q, NULL, NULL, - NULL, mp)) + if (match_pfx(p, q, NULL, NULL, + NULL, NULL, mp)) break; - if (k) { + if (k && i) { if (nlp) { nw = addtoword(&rw, &rwlen, nw, mp, l - mp->llen, w - i, @@ -2151,10 +2210,10 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm) ((mp->flags & CMF_LEFT) ? CLF_SUF : 0)); } - w = q; + w = q + 1; iw = j; lw = k; - l = p; + l = p + 1; il = jj; ll = kk; bc -= i; @@ -2395,20 +2454,45 @@ instmatch(Cmatch m) /**/ void addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, - char *suf, char *group, - int flags, int quote, int menu, int nosort, int alt, char **argv) + char *suf, char *group, char *rems, + int flags, int aflags, Cmatcher match, char **argv) { - char *s, *t; - int lpl, lsl, i; - Aminfo ai = (alt ? fainfo : ainfo); + char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf; + int lpl, lsl, i, pl, sl, test, bpl, bsl, lsm, llpl; + Aminfo ai; + Cline lc = NULL; + LinkList l; Cmatch cm; + struct cmlist mst; + Cmlist oms = mstack; - if (menu && isset(AUTOMENU)) + if (aflags & CAF_ALT) { + l = fmatches; + ai = fainfo; + } else { + l = matches; + ai = ainfo; + } + if (match) { + mst.next = mstack; + mst.matcher = match; + mstack = &mst; + } + if ((aflags & CAF_MENU) && isset(AUTOMENU)) usemenu = 1; SWITCHHEAPS(compheap) { HEAPALLOC { + if (aflags & CAF_MATCH) { + ctokenize(lipre = dupstring(compiprefix)); + remnulargs(lipre); + ctokenize(lpre = dupstring(compprefix)); + remnulargs(lpre); + llpl = strlen(lpre); + ctokenize(lsuf = dupstring(compsuffix)); + remnulargs(lsuf); + } if (ipre) - ipre = dupstring(ipre); + ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre)); if (ppre) { ppre = dupstring(ppre); lpl = strlen(ppre); @@ -2419,6 +2503,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, lsl = strlen(psuf); } else lsl = 0; + if (aflags & CAF_MATCH) + lsm = (psuf ? !strcmp(psuf, lsuf) : (!lsuf || !*lsuf)); if (pre) pre = dupstring(pre); if (suf) @@ -2430,10 +2516,12 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, prpre = dupstring(prpre); if (group) { endcmgroup(NULL); - begcmgroup(group, nosort); - if (nosort) + begcmgroup(group, (aflags & CAF_NOSORT)); + if (aflags & CAF_NOSORT) mgroup->flags |= CGF_NOSORT; } + if (rems) + rems = dupstring(rems); if (ai->pprefix) { if (pre) ai->pprefix[pfxlen(ai->pprefix, pre)] = '\0'; @@ -2442,10 +2530,54 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, } else ai->pprefix = dupstring(pre ? pre : ""); - for (; (s = *argv); argv++) { - if (ai->firstm) { - if ((i = pfxlen(ai->firstm->str, s)) < ai->prerest) - ai->prerest = i; + for (; (s = dupstring(*argv)); argv++) { + sl = strlen(s); + ms = NULL; + bpl = brpl; + bsl = brsl; + if ((!psuf || !*psuf) && (aflags & CAF_FIGNORE)) { + char **pt = fignore; + int filell; + + for (test = 1; test && *pt; pt++) + if ((filell = strlen(*pt)) < sl + && !strcmp(*pt, s + sl - filell)) + test = 0; + + if (!test) { + l = fmatches; + ai = fainfo; + } else { + l = matches; + ai = ainfo; + } + } + if (aflags & CAF_MATCH) { + t = (ppre ? dyncat(ppre, s) : s); + pl = sl + lpl; + if ((test = (llpl <= pl && !strncmp(t, lpre, pl)))) + test = lsm; + if (!test && mstack && + (ms = comp_match(lpre, lsuf, + (psuf ? dyncat(t, psuf) : t), + &lc, (aflags & CAF_QUOTE), + &bpl, &bsl))) + test = 1; + if (!test) + continue; + e = s + sl; + } else { + e = s; + pl = lpl; + } + if (!(aflags & CAF_QUOTE)) { + te = s + pl; + s = quotename(s, &e, te, &pl); + sl = strlen(s); + } + if (!ms && ai->firstm) { + if (sl < ai->minlen) + ai->minlen = sl; if ((i = sfxlen(ai->firstm->str, s)) < ai->suflen) ai->suflen = i; } @@ -2453,15 +2585,20 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, if (ppre) t = dyncat(ppre, t); if (ipre && *ipre) { + Cline tlc = prepend_cline(ipre, lc); + ai->noipre = 0; - if (ai->icpl > lpl) - ai->icpl = lpl; - if (ai->icsl > lsl) - ai->icsl = lsl; - if (ai->iaprefix) - ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0'; - else - ai->iaprefix = dupstring(t); + if (!ms) { + if ((aflags & CAF_MATCH) || ai->icpl > pl) + ai->icpl = pl; + if ((aflags & CAF_MATCH) || ai->icsl > lsl) + ai->icsl = lsl; + if (ai->iaprefix) + ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0'; + else + ai->iaprefix = dupstring(t); + } else + ai->ilinecl = join_clines(ai->ilinecl, lc); if (ai->iprefix) { if (strcmp(ipre, ai->iprefix)) ai->iprefix = ""; @@ -2469,16 +2606,21 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, ai->iprefix = dupstring(ipre); t = dyncat(ipre, t); + lc = tlc; } else ai->iprefix = ""; - if (ai->cpl > lpl) - ai->cpl = lpl; - if (ai->csl > lsl) - ai->csl = lsl; - if (ai->aprefix) - ai->aprefix[pfxlen(ai->aprefix, t)] = '\0'; - else - ai->aprefix = dupstring(t); + if (!ms) { + if ((aflags & CAF_MATCH) || ai->cpl > pl) + ai->cpl = pl; + if ((aflags & CAF_MATCH) || ai->csl > lsl) + ai->csl = lsl; + if (ai->aprefix) + ai->aprefix[pfxlen(ai->aprefix, t)] = '\0'; + else + ai->aprefix = dupstring(t); + } else + ai->linecl = join_clines(ai->linecl, lc); + mnum++; ai->count++; @@ -2486,25 +2628,41 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, cm->ppre = ppre; cm->psuf = psuf; cm->prpre = prpre; - if (!quote) - s = quotename(s, NULL, NULL, NULL); - cm->str = dupstring(s); + cm->str = (ms ? ms : dupstring(s)); cm->ipre = cm->ripre = ipre; cm->pre = pre; cm->suf = suf; cm->flags = flags; - cm->brpl = brpl; - cm->brsl = brsl; - addlinknode((alt ? fmatches : matches), cm); - - if (expl) - expl->fcount++; - if (!ai->firstm) - ai->firstm = cm; + cm->brpl = bpl; + cm->brsl = bsl; + cm->rems = rems; + addlinknode(l, cm); + + if (expl) { + if (l == matches) + expl->count++; + else + expl->fcount++; + } + if (!ms) { + if (!ai->firstm) + ai->firstm = cm; + if ((aflags & CAF_MATCH) && !(e - (s + pl))) { + if (!ai->exact) + ai->exact = 1; + else { + ai->exact = 2; + cm = NULL; + } + ai->exactm = cm; + } + } } compnmatches = mnum; } LASTALLOC; } SWITCHBACKHEAPS; + + mstack = oms; } /* This adds a match to the list of matches. The string to add is given * @@ -2685,8 +2843,8 @@ addmatch(char *s, char *t) if (!test) return; if (!ms && !ispattern && ai->firstm) { - if ((test = sl - pfxlen(ai->firstm->str, s)) < ai->prerest) - ai->prerest = test; + if (sl < ai->minlen) + ai->minlen = sl; if ((test = sfxlen(ai->firstm->str, s)) < ai->suflen) ai->suflen = test; } @@ -2716,8 +2874,7 @@ addmatch(char *s, char *t) ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0'; else ai->iaprefix = dupstring(t); - } - else + } else ai->ilinecl = join_clines(ai->ilinecl, lc); if (ai->iprefix) { if (strcmp(ipre, ai->iprefix)) @@ -2737,8 +2894,7 @@ addmatch(char *s, char *t) ai->aprefix[pfxlen(ai->aprefix, t)] = '\0'; else ai->aprefix = dupstring(t); - } - else + } else ai->linecl = join_clines(ai->linecl, lc); mnum++; @@ -2780,6 +2936,7 @@ addmatch(char *s, char *t) cm->flags = mflags | isf; cm->brpl = bpl; cm->brsl = bsl; + cm->rems = NULL; addlinknode(l, cm); /* One more match for this explanation. */ @@ -3211,7 +3368,12 @@ callcompfunc(char *s, char *fn) case IN_ENV: compcontext = "value"; compcommand = varname; - usea = 0; + if (!clwpos) { + clwpos = 1; + zsfree(clwords[1]); + clwords[1] = ztrdup(s); + } + aadd = 1; break; case IN_COND: compcontext = "condition"; @@ -3305,17 +3467,19 @@ makecomplist(char *s, int incmd, int lst) if (validlist) return !nmatches; + compmatcher = 1; for (;;) { if (m) { ms.next = NULL; ms.matcher = m->matcher; mstack = &ms; - } + } else + mstack = NULL; ainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); fainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); - ainfo->prerest = ainfo->suflen = - fainfo->prerest = fainfo->suflen = 10000; + ainfo->minlen = ainfo->suflen = + fainfo->minlen = fainfo->suflen = 10000; ainfo->noipre = fainfo->noipre= 1; freecl = NULL; @@ -3358,12 +3522,14 @@ makecomplist(char *s, int incmd, int lst) break; errflag = 0; + compmatcher++; } return 1; } /* This should probably be moved into tokenize(). */ +/**/ static char * ctokenize(char *p) { @@ -3564,10 +3730,11 @@ makecomplistcmd(char *os, int incmd, int flags) } /* Then search the pattern compctls, with the command name and the * * full pathname of the command. */ - makecomplistpc(os, incmd); - if (!(ccont & CC_CCCONT)) - return; - + if (cmdstr) { + makecomplistpc(os, incmd); + if (!(ccont & CC_CCCONT)) + return; + } /* If the command string starts with `=', try the path name of the * * command. */ if (cmdstr && cmdstr[0] == Equals) { @@ -5057,6 +5224,7 @@ dupmatch(Cmatch m) r->flags = m->flags; r->brpl = m->brpl; r->brsl = m->brsl; + r->rems = ztrdup(m->rems); return r; } @@ -5168,6 +5336,7 @@ freematch(Cmatch m) zsfree(m->ppre); zsfree(m->psuf); zsfree(m->prpre); + zsfree(m->rems); zfree(m, sizeof(m)); } @@ -5325,10 +5494,11 @@ do_ambiguous(void) * on the next call to completion the inserted string would be * * taken as a match and no menu completion would be started. */ - if (isset(RECEXACT) && !lc && !ainfo->prerest) + if (isset(RECEXACT) && !lc && ps && ainfo->minlen == strlen(ps)) am = 1; - /* If the LIST_AMBIGUOUS option (meaning roughly `show a list only * + /* + * If the LIST_AMBIGUOUS option (meaning roughly `show a list only * * if the completion is completely ambiguous') is set, and some * * prefix was inserted, return now, bypassing the list-displaying * * code. On the way, invalidate the list and note that we don't * @@ -5344,7 +5514,8 @@ do_ambiguous(void) * if it is needed. */ if (isset(LISTBEEP)) feep(); - if (isset(AUTOLIST) && !amenu && !showinglist && smatches >= 2) + if (isset(AUTOLIST) && !isset(BASHAUTOLIST) && !amenu && !showinglist && + smatches >= 2) showinglist = -2; if (am) lastambig = 1; @@ -5420,7 +5591,7 @@ do_single(Cmatch m) if (menuwe) { menuend += menuinsc; if (m->flags & CMF_REMOVE) { - makesuffix(menuinsc); + makesuffixstr(m->rems, menuinsc); if (menuinsc == 1) suffixlen[STOUC(m->suf[0])] = 1; } diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index e699e438c..a116921b4 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -816,6 +816,10 @@ viswapcase(void) void vicapslockpanic(void) { + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; zbeep(); statusline = "press a lowercase key to continue"; statusll = strlen(statusline); |