% zmodload zsh/complist % bindkey '^I' menu-select % MENUMODE=interactive % touch test{1,2} % : ; foobar ^ 1. Type the above line in its entirety. 2. Place the cursor before the ; 3. Press Tab. 4. Press Enter. % : test1 bar ^ Completion is written over existing buffer contents.
Hello,
I think I have an acceptable solution to this
issue, although I’m quite unaware of all the intricacies of the
Zsh source code,
and had 0 knowledge of Zsh internals until 2 days ago...
All I can say is that it doesn’t cause the tests to fail,
And that after a day of usage it doesn’t seem to break anything
else (in my limited use-cases).
Basically, when entering an interactive select
completion menu, the first completion in the list gets
“selected” (it’s highlighted) but not inserted in the command
line.
In the above test case, that would be “test1”.
At that time, compresult.c:do_single
was called with “test1” completion, then complist.c:domenuselect
restored the command line to its original content.
That means the minfo struct was
updated by do_single. In that case,
we would get minfo { .len = 5, .end = 7 }.
When leaving the
interactive mode (pressing Enter to accept the first completion,
or selecting another completion like using arrow keys),
minfo.len characters are
removed to “insert the next” completion (5 characters, but in
fact our command line is still “: ; foobar”,
so only 1 character should be erased).
So I just tried fixing it by correcting the values
in minfo when domenuselect
restores the command line content,
Which seems to me, is what should happen as far as I understand
:
diff --git a/Src/Zle/complist.c
b/Src/Zle/complist.c
index 9cb89a60d..f2eb3837d 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -2443,6 +2443,8 @@ domenuselect(Hookdef dummy, Chdata dat)
strncpy(zlemetaline, origline, l);
zlemetacs = origcs;
setmstatus(status, NULL, 0 , 0, NULL, NULL, NULL);
+ minfo.len = origlpre;
+ minfo.end = minfo.pos + minfo.len;
} else if (strpfx("search", s)) {
mode = (strstr(s, "back") ? MM_BSEARCH :
MM_FSEARCH);
}