about summary refs log tree commit diff
path: root/Src/Zle
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle')
-rw-r--r--Src/Zle/comp.h5
-rw-r--r--Src/Zle/comp1.c7
-rw-r--r--Src/Zle/compctl.c36
-rw-r--r--Src/Zle/zle_hist.c10
-rw-r--r--Src/Zle/zle_keymap.c4
-rw-r--r--Src/Zle/zle_main.c5
-rw-r--r--Src/Zle/zle_misc.c49
-rw-r--r--Src/Zle/zle_params.c28
-rw-r--r--Src/Zle/zle_refresh.c12
-rw-r--r--Src/Zle/zle_tricky.c115
-rw-r--r--Src/Zle/zle_vi.c5
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);