diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 5 | ||||
-rw-r--r-- | Src/Zle/comp1.c | 7 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 36 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 10 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 4 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 5 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 49 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 28 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 12 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 115 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 5 |
11 files changed, 201 insertions, 75 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 5f263557a..124ae454a 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -211,6 +211,7 @@ struct cmatch { int brpl; /* the place where to put the brace prefix */ int brsl; /* ...and the suffix */ char *rems; /* when to remove the suffix */ + char *remf; /* shell function to call for suffix-removal */ }; #define CMF_FILE 1 /* this is a file */ @@ -228,6 +229,7 @@ struct cmlist { }; struct cmatcher { + int refc; /* reference counter */ Cmatcher next; /* next matcher */ int flags; /* see CMF_* below */ Cpattern line; /* what matches on the line */ @@ -280,5 +282,4 @@ struct cline { #define CAF_MENU 2 #define CAF_NOSORT 4 #define CAF_ALT 8 -#define CAF_FIGNORE 16 -#define CAF_MATCH 32 +#define CAF_MATCH 16 diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index a5e35bc3c..77fe0a1fe 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 *, char *, int, int, Cmatcher, char **)); +void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **)); /**/ char *(*comp_strptr) _((int*,int*)); @@ -61,7 +61,7 @@ int (*getcpatptr) _((char *, int, char *, int)); void (*makecomplistcallptr) _((Compctl)); /**/ -void (*makecomplistctlptr) _((int)); +int (*makecomplistctlptr) _((int)); /* Hash table for completion info for commands */ @@ -249,6 +249,9 @@ freecmatcher(Cmatcher m) { Cmatcher n; + if (!m || --(m->refc)) + return; + while (m) { n = m->next; freecpattern(m->line); diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index dcc206c96..cec71fc5b 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -38,6 +38,7 @@ #define COMP_DEFAULT (1<<2) /* -D */ #define COMP_FIRST (1<<3) /* -T */ #define COMP_REMOVE (1<<4) +#define COMP_LISTMATCH (1<<5) /* -L and -M */ #define COMP_SPECIAL (COMP_COMMAND|COMP_DEFAULT|COMP_FIRST) @@ -82,6 +83,7 @@ cpcmatcher(Cmatcher m) while (m) { *p = n = (Cmatcher) zalloc(sizeof(struct cmatcher)); + n->refc = 1; n->next = NULL; n->flags = m->flags; n->line = cpcpattern(m->line); @@ -712,7 +714,9 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl) cct.mask2 |= CC_NOSORT; break; case 'M': - if ((*argv)[1]) { + if (cclist & COMP_LIST) { + cclist |= COMP_LISTMATCH; + } else if ((*argv)[1]) { if ((cct.matcher = parse_cmatcher(name, (cct.mstr = (*argv) + 1))) == pcm_err) { @@ -1572,7 +1576,7 @@ bin_compctl(char *name, char **argv, char *ops, int func) /* If no commands and no -C, -T, or -D, print all the compctl's * * If some flags (other than -C, -T, or -D) were given, then * * only print compctl containing those flags. */ - if (!*argv && !(cclist & COMP_SPECIAL)) { + if (!*argv && !(cclist & (COMP_SPECIAL|COMP_LISTMATCH))) { Patcomp pc; for (pc = patcomps; pc; pc = pc->next) @@ -1619,6 +1623,8 @@ bin_compctl(char *name, char **argv, char *ops, int func) printcompctl("", &cc_default, 0, 0); if (cclist & COMP_FIRST) printcompctl("", &cc_first, 0, 0); + if (cclist & COMP_LISTMATCH) + print_gmatcher(COMP_LIST); return ret; } @@ -1670,6 +1676,7 @@ 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, *m = NULL, *rs = NULL; + char *ign = NULL, *rf = NULL; int f = 0, a = 0, dm; Cmatcher match = NULL; @@ -1692,7 +1699,8 @@ bin_compadd(char *name, char **argv, char *ops, int func) f |= CMF_FILE; break; case 'F': - a |= CAF_FIGNORE; + sp = &ign; + e = "string expected after -%c"; break; case 'n': f |= CMF_NOLIST; @@ -1746,9 +1754,15 @@ bin_compadd(char *name, char **argv, char *ops, int func) dm = 1; break; case 'r': + f |= CMF_REMOVE; sp = &rs; e = "string expected after -%c"; break; + case 'R': + f |= CMF_REMOVE; + sp = &rf; + e = "function name expected after -%c"; + break; case '-': argv++; goto ca_args; @@ -1782,8 +1796,11 @@ bin_compadd(char *name, char **argv, char *ops, int func) if (!*argv) return 1; + match = cpcmatcher(match); addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group, - rs, f, a, match, argv); + rs, rf, ign, f, a, match, argv); + freecmatcher(match); + return 0; } @@ -1795,9 +1812,8 @@ bin_compcall(char *name, char **argv, char *ops, int func) zerrnam(name, "can only be called from completion function", NULL, 0); return 1; } - makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) | - (ops['D'] ? 0 : CFN_DEFAULT)); - return 0; + return makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) | + (ops['D'] ? 0 : CFN_DEFAULT)); } #define VAR(X) ((void *) (&(X))) @@ -2016,7 +2032,7 @@ cond_strcl(char **a, int id) { if (comp_check()) { char *s; - int i; + int i, ipl; if (a[1]) { s = cond_str(a, 1); @@ -2029,9 +2045,9 @@ cond_strcl(char **a, int id) zerr("zle not loaded, zle condition not available", NULL, 0); return 1; } - i = getcpatptr(comp_strptr(NULL, NULL), i, s, id); + i = getcpatptr(comp_strptr(&ipl, NULL), i, s, id); if (i != -1) { - ignore_prefix(i); + ignore_prefix(i - ipl); return 1; } } diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index e6b385652..a4b3866e5 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -663,10 +663,7 @@ doisearch(int dir) static char *previous_search = NULL; static int previous_search_len = 0; - invalidatelist(); - moveto(0, 0); - clearflag = 0; - resetneeded = 1; + clearlist = 1; strcpy(ibuf, ISEARCH_PROMPT); memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); @@ -948,10 +945,7 @@ getvisrchstr(void) zsfree(visrchstr); visrchstr = NULL; } - invalidatelist(); - moveto(0, 0); - clearflag = 0; - resetneeded = 1; + clearlist = 1; statusline = sbuf; sbuf[0] = (visrchsense == -1) ? '?' : '/'; selectkeymap("main", 1); diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 1ffe6f156..1baa3a845 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -108,7 +108,9 @@ static HashTable keymapnamtab; /* key sequence reading data */ -static char *keybuf; +/**/ +char *keybuf; + static int keybuflen, keybufsz = 20; /* last command executed with execute-named-command */ diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index ca7a7fe19..277d154a6 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -792,10 +792,7 @@ describekeybriefly(void) if (statusline) return; - invalidatelist(); - moveto(0, 0); - clearflag = 0; - resetneeded = 1; + clearlist = 1; statusline = "Describe key briefly: _"; statusll = strlen(statusline); zrefresh(); diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 4b5df9cde..ea8874010 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -612,10 +612,7 @@ executenamedcommand(char *prmt) char *ptr; char *okeymap = curkeymapname; - invalidatelist(); - moveto(0, 0); - clearflag = 0; - resetneeded = 1; + clearlist = 1; cmdbuf = halloc(l + NAMLEN + 2); strcpy(cmdbuf, prmt); statusline = cmdbuf; @@ -767,6 +764,11 @@ executenamedcommand(char *prmt) /**/ int suffixlen[257]; +/* Shell function to call to remove the suffix. */ + +/**/ +static char *suffixfunc; + /* Set up suffix: the last n characters are a suffix that should be * * removed in the usual word end conditions. */ @@ -801,9 +803,13 @@ makeparamsuffix(int br, int n) /**/ void -makesuffixstr(char *s, int n) +makesuffixstr(char *f, char *s, int n) { - if (s) { + if (f) { + zsfree(suffixfunc); + suffixfunc = ztrdup(f); + suffixlen[0] = n; + } else if (s) { int inv, i, v, z = 0; if (*s == '^' || *s == '!') { @@ -845,10 +851,33 @@ makesuffixstr(char *s, int n) void iremovesuffix(int c) { - int sl = suffixlen[c]; - if(sl) { - backdel(sl); - invalidatelist(); + if (suffixfunc) { + List l = getshfunc(suffixfunc); + + if (l != &dummy_list) { + LinkList args = newlinklist(); + char buf[20]; + int osc = sfcontext; + + sprintf(buf, "%d", suffixlen[0]); + addlinknode(args, suffixfunc); + addlinknode(args, buf); + + startparamscope(); + makezleparams(0); + sfcontext = SFC_COMPLETE; + doshfunc(suffixfunc, l, args, 0, 1); + sfcontext = osc; + endparamscope(); + } + zsfree(suffixfunc); + suffixfunc = NULL; + } else { + int sl = suffixlen[c]; + if(sl) { + backdel(sl); + invalidatelist(); + } } fixsuffix(); } diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 74f905ef4..7e15d3d8b 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -65,6 +65,8 @@ static struct zleparam { zleunsetfn, NULL }, { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget), zleunsetfn, NULL }, + { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys), + zleunsetfn, NULL }, { NULL, 0, NULL, NULL, NULL, NULL } }; @@ -216,3 +218,29 @@ get_lwidget(Param pm) { return (lbindk ? lbindk->nam : ""); } + +/**/ +static char ** +get_keys(Param pm) +{ + char **r, **q, *p, *k, c; + + r = (char **) halloc((strlen(keybuf) + 1) * sizeof(char *)); + for (q = r, p = keybuf; (c = *p); q++, p++) { + k = *q = (char *) halloc(5); + if (c & 0x80) { + *k++ = 'M'; + *k++ = '-'; + c &= 0x7f; + } + if (c < 32 || c == 0x7f) { + *k++ = '^'; + c ^= 64; + } + *k++ = c; + *k = '\0'; + } + *q = NULL; + + return r; +} diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index c8d6c70a7..9e07676e8 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -60,6 +60,11 @@ int showinglist; /**/ int clearflag; +/* Non-zero if zrefresh() should clear the list below the prompt. */ + +/**/ +int clearlist; + #ifdef HAVE_SELECT /* cost of last update */ /**/ @@ -248,6 +253,13 @@ zrefresh(void) if (inlist) return; + if (clearlist) { + invalidatelist(); + moveto(0, 0); + clearflag = 0; + resetneeded = 1; + clearlist = 0; + } #ifdef HAVE_SELECT cost = 0; /* reset */ #endif diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index f1285da8c..f1078ef11 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -212,6 +212,10 @@ static LinkList ccstack; static Cmlist mstack; +/* A list with references to all matcher we used. */ + +static LinkList matchers; + /* A heap of free Cline structures. */ static Cline freecl; @@ -2454,10 +2458,10 @@ instmatch(Cmatch m) /**/ void addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, - char *suf, char *group, char *rems, + char *suf, char *group, char *rems, char *remf, char *ign, int flags, int aflags, Cmatcher match, char **argv) { - char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf; + char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf, **aign = NULL; int lpl, lsl, i, pl, sl, test, bpl, bsl, lsm, llpl; Aminfo ai; Cline lc = NULL; @@ -2477,22 +2481,26 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, mst.next = mstack; mst.matcher = match; mstack = &mst; + addlinknode(matchers, match); + match->refc++; } if ((aflags & CAF_MENU) && isset(AUTOMENU)) usemenu = 1; + if (ign) + aign = get_user_var(ign); + SWITCHHEAPS(compheap) { HEAPALLOC { if (aflags & CAF_MATCH) { - ctokenize(lipre = dupstring(compiprefix)); - remnulargs(lipre); - ctokenize(lpre = dupstring(compprefix)); - remnulargs(lpre); + lipre = dupstring(compiprefix); + lpre = dupstring(compprefix); llpl = strlen(lpre); - ctokenize(lsuf = dupstring(compsuffix)); - remnulargs(lsuf); + lsuf = dupstring(compsuffix); } if (ipre) ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre)); + else if (lipre) + ipre = lipre; if (ppre) { ppre = dupstring(ppre); lpl = strlen(ppre); @@ -2520,7 +2528,10 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, if (aflags & CAF_NOSORT) mgroup->flags |= CGF_NOSORT; } - if (rems) + if (remf) { + remf = dupstring(remf); + rems = NULL; + } else if (rems) rems = dupstring(rems); if (ai->pprefix) { if (pre) @@ -2535,8 +2546,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, ms = NULL; bpl = brpl; bsl = brsl; - if ((!psuf || !*psuf) && (aflags & CAF_FIGNORE)) { - char **pt = fignore; + if ((!psuf || !*psuf) && aign) { + char **pt = aign; int filell; for (test = 1; test && *pt; pt++) @@ -2635,6 +2646,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, cm->flags = flags; cm->brpl = bpl; cm->brsl = bsl; + cm->remf = remf; cm->rems = rems; addlinknode(l, cm); @@ -2936,7 +2948,7 @@ addmatch(char *s, char *t) cm->flags = mflags | isf; cm->brpl = bpl; cm->brsl = bsl; - cm->rems = NULL; + cm->rems = cm->remf = NULL; addlinknode(l, cm); /* One more match for this explanation. */ @@ -3259,17 +3271,20 @@ static void docompletion(char *s, int lst, int incmd) { HEAPALLOC { + LinkNode n; + pushheap(); ainfo = fainfo = NULL; + matchers = newlinklist(); /* Make sure we have the completion list and compctl. */ if (makecomplist(s, incmd, lst)) { /* Error condition: feeeeeeeeeeeeep(). */ feep(); + clearlist = 1; goto compend; } - if (lst == COMP_LIST_COMPLETE) /* All this and the guy only wants to see the list, sigh. */ showinglist = -2; @@ -3324,6 +3339,9 @@ docompletion(char *s, int lst, int incmd) } } compend: + for (n = firstnode(matchers); n; incnode(n)) + freecmatcher((Cmatcher) getdata(n)); + ll = strlen((char *)line); if (cs > ll) cs = ll; @@ -3460,13 +3478,26 @@ static int makecomplist(char *s, int incmd, int lst) { struct cmlist ms; - Cmlist m = cmatcher; + Cmlist m; /* If we already have a list from a previous execution of this * * function, skip the list building code. */ if (validlist) return !nmatches; + if ((m = cmatcher)) { + Cmlist mm, *mp = &mm; + + for (; m; m = m->next) { + *mp = (Cmlist) halloc(sizeof(struct cmlist)); + (*mp)->matcher = m->matcher; + (*mp)->next = NULL; + mp = &((*mp)->next); + addlinknode(matchers, m->matcher); + m->matcher->refc++; + } + m = mm; + } compmatcher = 1; for (;;) { if (m) { @@ -3613,11 +3644,13 @@ static int cdepth = 0; #define MAX_CDEPTH 16 /**/ -void +int makecomplistctl(int flags) { + int ret; + if (cdepth == MAX_CDEPTH) - return; + return 0; cdepth++; SWITCHHEAPS(compheap) { @@ -3641,9 +3674,10 @@ makecomplistctl(int flags) *q = NULL; offs = lip + lp; incompfunc = 2; - makecomplistglobal(str, - (!clwpos && !strcmp(compcontext, "command")), - COMP_COMPLETE, flags); + ret = makecomplistglobal(str, + (!clwpos && + !strcmp(compcontext, "command")), + COMP_COMPLETE, flags); incompfunc = 1; offs = ooffs; compnmatches = mnum; @@ -3656,13 +3690,15 @@ makecomplistctl(int flags) } LASTALLOC; } SWITCHBACKHEAPS; cdepth--; + + return ret; } /* This function gets the compctls for the given command line and * * adds all completions for them. */ /**/ -static void +static int makecomplistglobal(char *os, int incmd, int lst, int flags) { Compctl cc; @@ -3694,46 +3730,48 @@ makecomplistglobal(char *os, int incmd, int lst, int flags) } else if (linredir) /* In redirections use default completion. */ cc = &cc_default; - else { + else /* Otherwise get the matches for the command. */ - makecomplistcmd(os, incmd, flags); - cc = NULL; - } + return makecomplistcmd(os, incmd, flags); + if (cc) { /* First, use the -T compctl. */ if (!(flags & CFN_FIRST)) { makecomplistcc(&cc_first, os, incmd); if (!(ccont & CC_CCCONT)) - return; + return 0; } makecomplistcc(cc, os, incmd); + return 1; } + return 0; } /* This produces the matches for a command. */ /**/ -static void +static int makecomplistcmd(char *os, int incmd, int flags) { Compctl cc; Compctlp ccp; char *s; + int ret = 0; /* First, use the -T compctl. */ if (!(flags & CFN_FIRST)) { makecomplistcc(&cc_first, os, incmd); if (!(ccont & CC_CCCONT)) - return; + return 0; } /* Then search the pattern compctls, with the command name and the * * full pathname of the command. */ if (cmdstr) { - makecomplistpc(os, incmd); + ret |= makecomplistpc(os, incmd); if (!(ccont & CC_CCCONT)) - return; + return ret; } /* If the command string starts with `=', try the path name of the * * command. */ @@ -3758,31 +3796,36 @@ makecomplistcmd(char *os, int incmd, int flags) (ccp = (Compctlp) compctltab->getnode(compctltab, s)) && (cc = ccp->cc))))) { if (flags & CFN_DEFAULT) - return; + return ret; cc = &cc_default; - } + } else + ret|= 1; makecomplistcc(cc, os, incmd); + return ret; } /* This add the matches for the pattern compctls. */ /**/ -static void +static int makecomplistpc(char *os, int incmd) { Patcomp pc; Comp pat; char *s = findcmd(cmdstr, 1); + int ret = 0; for (pc = patcomps; pc; pc = pc->next) { if ((pat = parsereg(pc->pat)) && (domatch(cmdstr, pat, 0) || (s && domatch(s, pat, 0)))) { makecomplistcc(pc->cc, os, incmd); + ret |= 2; if (!(ccont & CC_CCCONT)) - return; + return ret; } } + return ret; } /* This produces the matches for one compctl. */ @@ -4111,6 +4154,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) ms.next = mstack; ms.matcher = cc->matcher; mstack = &ms; + addlinknode(matchers, cc->matcher); + cc->matcher->refc++; } /* Insert the prefix (compctl -P), if any. */ if (cc->prefix) { @@ -5225,6 +5270,7 @@ dupmatch(Cmatch m) r->brpl = m->brpl; r->brsl = m->brsl; r->rems = ztrdup(m->rems); + r->remf = ztrdup(m->remf); return r; } @@ -5337,6 +5383,7 @@ freematch(Cmatch m) zsfree(m->psuf); zsfree(m->prpre); zsfree(m->rems); + zsfree(m->remf); zfree(m, sizeof(m)); } @@ -5591,7 +5638,7 @@ do_single(Cmatch m) if (menuwe) { menuend += menuinsc; if (m->flags & CMF_REMOVE) { - makesuffixstr(m->rems, menuinsc); + makesuffixstr(m->remf, 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 a116921b4..2e4fb4a32 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -816,10 +816,7 @@ viswapcase(void) void vicapslockpanic(void) { - invalidatelist(); - moveto(0, 0); - clearflag = 0; - resetneeded = 1; + clearlist = 1; zbeep(); statusline = "press a lowercase key to continue"; statusll = strlen(statusline); |