Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: fix complist interactive mode overwriting buffer



On Sun, May 24, 2026 at 1:49 AM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> On Sat, May 23, 2026 at 4:26 PM Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
> >
> > If someone who uses interactive menu selection a lot feels like
> > testing these out, that would be helpful.
>
> Thanks for figuring this one out, it's been on my unresolved list for
> a long time.
>
> I've directly Cc'd Andrea and Marlon who each reported this problem at
> different times.

Thanks, I meant to do that but then it slipped my mind when I was
sending the patches out together.

Dana was talking about completing quoted words and I realized I hadn't
tried that at all, and it indeed doesn't work well very well.

First we have the interactive menu selection case like this:
% ls "<enter IMS, type NE and hit enter>
% ls "NEWS" <cursor here>E

    During completion, the quote tokens are temporarily removed, and we is
    decremented (this all happens in get_comp_string, around the parts
    involving skipchars, I would advise not looking too closely). Then the
    complist code restores the original string via setmline but forgot to
    restore we. I don't think there's any point in trying to track exactly
    how many characters were deleted to add them back, just set it back to
    the cursor position.
---
 Src/Zle/complist.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index f4b4df6c21..f4d22a968e 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -2779,9 +2779,13 @@ domenuselect(Hookdef dummy, Chdata dat)
            metafy_line();
            iforcemenu = 0;

-            if (cmd != Th(z_acceptandinfernexthistory))
+            if (cmd != Th(z_acceptandinfernexthistory)) {
                 modeline = setmstatus(status, saveline, savell, savecs,
                                       &modecs, &modell, &modelen);
+               /* if we are completing a quoted word, by this point we've
+                * lost track of this, so put we back where it should be */
+               we = savecs;
+           }

            if (nmatches < 1 || !minfo.cur || !*(minfo.cur)) {
                nolist = 1;


And secondly, this bug doesn't even involve the interactive mode.
% ls "stam<enter regular menu selection, hit alt-a (more than once if you want)>
% ls "stamp.h" stamp.h" stamp.h" stamp.h"

    Fix accept-and-hold completion for words with leading quotes

    The intention here is to skip leading braces probably, but that is
    a no-op because m->qipl is 0 in that case. When there is a quote, we
    don't want to skip it, so just remove that thing.
---
 Src/Zle/compresult.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index e3aa679ab2..3a73a2dd9f 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -588,9 +588,7 @@ instmatch(Cmatch m, int *scs)

     /* Ignored prefix. */
     if (m->ipre) {
-       char *p = m->ipre + (menuacc ? m->qipl : 0);
-
-       inststrlen(p, 1, (l = strlen(p)));
+       inststrlen(m->ipre, 1, (l = strlen(m->ipre)));
        r += l;
     }
     /* -P prefix. */


This is probably becoming a pain to try to apply manually, so I'll
attach the combined patch for anyone looking to try it out, although
at this point maybe I should just push?

-- 
Mikael Magnusson
diff --git c/Src/Zle/complist.c w/Src/Zle/complist.c
index 6a46497954..f4d22a968e 100644
--- c/Src/Zle/complist.c
+++ w/Src/Zle/complist.c
@@ -2640,6 +2640,7 @@ domenuselect(Hookdef dummy, Chdata dat)
     	}
 	do_last_key = 0;
 
+	int was_inter = (mode == MM_INTER);
 	if (!cmd || cmd == Th(z_sendbreak)) {
 	    zbeep();
             molbeg = -1;
@@ -2778,9 +2779,13 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    metafy_line();
 	    iforcemenu = 0;
 
-            if (cmd != Th(z_acceptandinfernexthistory))
+            if (cmd != Th(z_acceptandinfernexthistory)) {
                 modeline = setmstatus(status, saveline, savell, savecs,
                                       &modecs, &modell, &modelen);
+		/* if we are completing a quoted word, by this point we've
+		 * lost track of this, so put we back where it should be */
+		we = savecs;
+	    }
 
 	    if (nmatches < 1 || !minfo.cur || !*(minfo.cur)) {
 		nolist = 1;
@@ -2822,8 +2827,12 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
-	    if (mode == MM_INTER)
-		do_single(*minfo.cur);
+	    if (mode == MM_INTER) {
+		Cmatch *cur = minfo.cur;
+		minfo.cur = NULL;
+		do_single(*cur);
+		minfo.cur = cur;
+	    }
 	    mode = 0;
 	    s->prev = u;
 	    u = s;
@@ -3279,6 +3288,7 @@ domenuselect(Hookdef dummy, Chdata dat)
                 strncpy(zlemetaline, origline, origll);
                 zlemetacs = origcs;
                 minfo.len = modelen;
+                we = wb + modelen;
             } else {
                 mode = 0;
                 comprecursive = 1;
@@ -3407,6 +3417,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 		acc = 1;
 	    break;
 	}
+	if (was_inter)
+	    minfo.cur = NULL;
 	do_single(**p);
 	mselect = (**p)->gnum;
     }
@@ -3423,7 +3435,12 @@ domenuselect(Hookdef dummy, Chdata dat)
         clearlist = listshown = 1;
     if (acc && validlist && minfo.cur) {
 	menucmp = lastambig = hasoldlist = 0;
-	do_single(*(minfo.cur));
+	if (mode == MM_INTER) {
+	    Cmatch *cur = minfo.cur;
+	    minfo.cur = NULL;
+	    do_single(*cur);
+	} else
+	    do_single(*(minfo.cur));
     }
     if (wasnext || broken) {
 	menucmp = 1;
diff --git c/Src/Zle/compresult.c w/Src/Zle/compresult.c
index e3aa679ab2..3a73a2dd9f 100644
--- c/Src/Zle/compresult.c
+++ w/Src/Zle/compresult.c
@@ -588,9 +588,7 @@ instmatch(Cmatch m, int *scs)
 
     /* Ignored prefix. */
     if (m->ipre) {
-	char *p = m->ipre + (menuacc ? m->qipl : 0);
-
-	inststrlen(p, 1, (l = strlen(p)));
+	inststrlen(m->ipre, 1, (l = strlen(m->ipre)));
 	r += l;
     }
     /* -P prefix. */


Messages sorted by: Reverse Date, Date, Thread, Author