Re: PATCH: fix complist interactive mode overwriting buffer
Mikael Magnusson <[email protected]>
| Newsgroups | gmane.comp.shells.zsh.devel |
|---|---|
| Message-ID | <CAHYJk3RMxsN6uNHSDEfKX3W5JaEY5X1BQT6PJ=w8gaBGTCYO0Q@mail.gmail.com> |
On Sun, May 24, 2026 at 1:49 AM Bart Schaefer <[email protected]> wrote: > > On Sat, May 23, 2026 at 4:26 PM Mikael Magnusson <[email protected]> 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
ims.patch
(text/x-patch, 2.6 KB)
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. */