diff --git a/src/tui/light.go b/src/tui/light.go index b5557dc4..32dd5a7a 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -630,20 +630,35 @@ func (r *LightRenderer) setCancel(f func()) { r.mutex.Unlock() } -// escSequence parses an escape sequence, widening a CSI or SS3 sequence that -// parseEscSequence recognized the start of but gave up on partway. Consuming -// only the part that parsed would leave the rest to be read as input and typed -// into the query. Complete sequences it does not recognize are dropped there, -// unless they could be an ALT key followed by typed text. +// escSequence parses an escape sequence, then checks a CSI or SS3 result +// against its frame. parseEscSequence can stop after a few bytes, and consuming +// only those would leave the rest to be typed into the query. Complete +// sequences it does not recognize are dropped there, unless they could be an +// ALT key followed by typed text. func (r *LightRenderer) escSequence(sz *int) Event { ev := r.parseEscSequence(sz) - if ev.Type != Invalid || len(r.buffer) < 3 || !csiIntroducer(r.buffer[1]) { + if len(r.buffer) < 3 || !csiIntroducer(r.buffer[1]) { return ev } - // Only a framed sequence is dropped. One still missing its final byte may - // yet be arriving, and the caller gives it another chance. - if end := csiEnd(r.buffer); end > *sz { + // A frame missing its final byte may still be arriving + end := csiEnd(r.buffer) + if end == 0 { + return ev + } + // The same rule as the fall-through: four bytes or fewer could be ALT-[ + // or ALT-O and typed text + if end <= 4 { + if ev.Type == Invalid { + *sz = 2 + return AltKey(rune(r.buffer[1])) + } + return ev + } + // A key matched on a prefix, such as Home for \e[70;5u, or a sequence + // given up on partway + if end > *sz { *sz = end + return Event{Invalid, 0, nil} } return ev } diff --git a/src/tui/light_csi_test.go b/src/tui/light_csi_test.go index 3a7ccb86..b7071b4b 100644 --- a/src/tui/light_csi_test.go +++ b/src/tui/light_csi_test.go @@ -13,6 +13,9 @@ func TestUnknownEscapeSequence(t *testing.T) { }{ // Key encodings fzf does not implement {"\x1b[97;5u", Invalid, 7}, + {"\x1b[70;5u", Invalid, 7}, // not Home, which its prefix \e[7 matches + {"\x1b[42;5u", Invalid, 7}, // nor End + {"\x1b[4;5~", Invalid, 6}, {"\x1b[127;5u", Invalid, 8}, {"\x1b[27;5;127~", Invalid, 11}, {"\x1b[57441;1u", Invalid, 10}, @@ -46,6 +49,10 @@ func TestUnknownEscapeSequence(t *testing.T) { {"\x1b[ x", Alt, 2}, {"\x1bOx", Alt, 2}, {"\x1bO9A", Alt, 2}, + {"\x1b[2m", Alt, 2}, // the parser gives up on these itself + {"\x1b[3x", Alt, 2}, + {"\x1b[