mirror of
https://github.com/junegunn/fzf.git
synced 2026-10-06 12:18:59 +08:00
Check the parser's CSI and SS3 results against the frame
The parser can stop after a few bytes. A key matched on a prefix kept only those: CTRL-F as \e[70;5u fired Home and typed ";5u". And a short sequence it gave up on was dropped, losing ALT-[ followed by "2m". - Drop the frame when a recognized key covers only part of one over 4 bytes - Report the ALT key for a complete unrecognized frame of 4 bytes or fewer, the same rule the fall-through applies Reported by Copilot on #4926.
This commit is contained in:
2 files changed
+31
-9
No files matched your search
+24
-9
@@ -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
|
||||
}
|
||||
|
||||
@@ -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[<a", Alt, 2},
|
||||
{"\x1bO<a", Alt, 2},
|
||||
{"\x1b]abc", Alt, 2},
|
||||
{"\x1b]11;rgb:", Alt, 2}, // terminator has not arrived
|
||||
{"\x1b]\x1b]", Alt, 2}, // a second sequence must not swallow the ALT key
|
||||
|
||||
Reference in new issue
Block a user