mirror of
https://github.com/junegunn/fzf.git
synced 2026-10-05 19:58:56 +08:00
Take the second chance only for an unfinished sequence
The check looked at the last ESC in the buffer, not at the sequence just parsed. A dropped \e[97;5u followed by CTRL-G and ALT-[ in one read blocked until the next key, holding back the abort. Require both to be unfinished: an unfinished sequence followed by other bytes cannot complete either. Reported by Copilot on #4926.
This commit is contained in:
2 files changed
+34
-4
No files matched your search
+12
-4
@@ -444,6 +444,14 @@ func stringReply(buffer []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// stillArriving reports whether the sequence that consumed sz bytes of the
|
||||
// buffer may still be completed by more input. Both it and the buffer have to
|
||||
// end unfinished: a complete sequence followed by ALT-[ is not waiting for
|
||||
// anything, and an unfinished one followed by other bytes cannot complete.
|
||||
func stillArriving(buffer []byte, sz int) bool {
|
||||
return incompleteEscape(buffer[:min(sz, len(buffer))]) && incompleteEscape(buffer)
|
||||
}
|
||||
|
||||
// incompleteEscape reports whether the buffer ends in an escape sequence that
|
||||
// has not been terminated yet. The read loop keeps waiting while it does, so a
|
||||
// fragment reaches the parser only once that wait has run out.
|
||||
@@ -578,10 +586,10 @@ func (r *LightRenderer) GetChar(cancellable bool) Event {
|
||||
return Event{CtrlSlash, 0, nil}
|
||||
case Esc.Byte():
|
||||
ev := r.escSequence(&sz)
|
||||
// Second chance, but only while the buffer ends in an unfinished
|
||||
// sequence. Re-reading otherwise blocks until the next keystroke,
|
||||
// holding back whatever follows in the buffer.
|
||||
if ev.Type == Invalid && incompleteEscape(r.buffer) {
|
||||
// Second chance, but only for an unfinished sequence. Re-reading
|
||||
// otherwise blocks until the next keystroke, holding back whatever
|
||||
// follows in the buffer.
|
||||
if ev.Type == Invalid && stillArriving(r.buffer, sz) {
|
||||
r.buffer, result, err = r.getBytes(true)
|
||||
if err != nil {
|
||||
return Event{Fatal, 0, nil}
|
||||
|
||||
@@ -127,6 +127,28 @@ func TestStringEnd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A dropped sequence followed by ALT-[ is not waiting for anything, so the
|
||||
// bytes in between must not be held back until the next keystroke
|
||||
func TestStillArriving(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
buffer string
|
||||
sz int
|
||||
want bool
|
||||
}{
|
||||
{"\x1b[97;5u\a\x1b[", 7, false},
|
||||
{"\x1b[97;5u\x1b[", 7, false},
|
||||
{"\x1b[1;\a", 4, false}, // the BEL has already ended it
|
||||
{"\x1b[1;", 4, true},
|
||||
{"\x1b[", 2, true},
|
||||
{"\x1bO1", 3, true},
|
||||
{"\x1b[<0;1", 3, true},
|
||||
} {
|
||||
if got := stillArriving([]byte(c.buffer), c.sz); got != c.want {
|
||||
t.Errorf("stillArriving(%q, %d) = %v, want %v", c.buffer, c.sz, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringReply(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
buffer string
|
||||
|
||||
Reference in new issue
Block a user