From 83cbe5b5914bfad7c06ba6356a6b37f5d9508d72 Mon Sep 17 00:00:00 2001 From: Mogwai <2012044+intestinate@users.noreply.github.com> Date: Sun, 5 Jul 2026 12:53:07 -0400 Subject: [PATCH] Handle legacy Linux console F1-F5 keys --- decoder.go | 13 +++++++++++++ key_test.go | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/decoder.go b/decoder.go index a891dc27..cd065196 100644 --- a/decoder.go +++ b/decoder.go @@ -316,6 +316,19 @@ func (p *EventDecoder) parseCsi(b []byte) (int, Event) { i++ } + // Linux console function keys F1-F5 are historically sent as + // ESC [ [ A through ESC [ [ E. The second '[' is not a valid CSI + // parameter, intermediate, or prefix byte, so no other sequence uses + // this form. Handle it explicitly before the normal CSI parsing. + if i < len(b) && b[i] == '[' { + if i+1 < len(b) { + if c := b[i+1]; c >= 'A' && c <= 'E' { + return i + 2, KeyPressEvent{Code: KeyF1 + rune(c-'A')} + } + } + return i + 1, UnknownCsiEvent(b[:i+1]) + } + // Initial CSI byte if i < len(b) && b[i] >= '<' && b[i] <= '?' { cmd |= ansi.Cmd(b[i]) << parser.PrefixShift diff --git a/key_test.go b/key_test.go index 38234814..e1c90c99 100644 --- a/key_test.go +++ b/key_test.go @@ -93,6 +93,27 @@ func buildBaseSeqTests() []seqTest { KeyPressEvent{Code: KeySpace, Mod: ModAlt}, }, }, + // Linux console function keys F1-F5 (ESC [ [ A .. ESC [ [ E). + seqTest{ + []byte("\x1b[[A"), + []Event{KeyPressEvent{Code: KeyF1}}, + }, + seqTest{ + []byte("\x1b[[B"), + []Event{KeyPressEvent{Code: KeyF2}}, + }, + seqTest{ + []byte("\x1b[[C"), + []Event{KeyPressEvent{Code: KeyF3}}, + }, + seqTest{ + []byte("\x1b[[D"), + []Event{KeyPressEvent{Code: KeyF4}}, + }, + seqTest{ + []byte("\x1b[[E"), + []Event{KeyPressEvent{Code: KeyF5}}, + }, ) return td }