mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
fix: Ctrl+Space (ToggleSelection) not working after tcell migration
tcellEventToEvent did not convert Ctrl+Space to KeyCtrlSpace for CSI u terminals or traditional terminals (tcell emits KeyCtrlSpace which fell outside the KeyCtrlA..KeyCtrlZ range).
This commit is contained in:
parent
1eab243c5e
commit
42c39e38c8
24
screen.go
24
screen.go
|
|
@ -110,8 +110,20 @@ func tcellEventToEvent(tev tcell.Event) Event {
|
|||
}
|
||||
}
|
||||
|
||||
// Special case: space must be sent as KeySpace with Ch=0
|
||||
// to match the convention expected by doAcceptChar
|
||||
// Ctrl+Space via CSI u: tcell delivers KeyRune with
|
||||
// rune=' ' and ModCtrl. Convert to KeyCtrlSpace (0x00).
|
||||
if r == ' ' && mod&keyseq.ModCtrl != 0 {
|
||||
mod &^= keyseq.ModCtrl
|
||||
return Event{
|
||||
Type: EventKey,
|
||||
Key: keyseq.KeyCtrlSpace,
|
||||
Ch: 0,
|
||||
Mod: mod,
|
||||
}
|
||||
}
|
||||
|
||||
// Plain space must be sent as KeySpace with Ch=0
|
||||
// to match the convention expected by doAcceptChar.
|
||||
if r == ' ' {
|
||||
return Event{
|
||||
Type: EventKey,
|
||||
|
|
@ -138,17 +150,17 @@ func tcellEventToEvent(tev tcell.Event) Event {
|
|||
}
|
||||
}
|
||||
|
||||
// Ctrl+letter keys: tcell.KeyCtrlA(65)..KeyCtrlZ(90).
|
||||
// Ctrl keys: tcell.KeyCtrlSpace(64)..KeyCtrlZ(90).
|
||||
// On terminals with enhanced keyboard protocols (CSI u /
|
||||
// fixterms), tcell normalizes Ctrl+letter to these constants
|
||||
// with ModCtrl set. Peco's keyseq system encodes the ctrl
|
||||
// nature in the key value (0x01-0x1A), not in the modifier,
|
||||
// nature in the key value (0x00-0x1A), not in the modifier,
|
||||
// so strip the redundant ModCtrl. (issue #715)
|
||||
if key >= tcell.KeyCtrlA && key <= tcell.KeyCtrlZ {
|
||||
if key >= tcell.KeyCtrlSpace && key <= tcell.KeyCtrlZ {
|
||||
mod &^= keyseq.ModCtrl
|
||||
return Event{
|
||||
Type: EventKey,
|
||||
Key: keyseq.KeyType(key - tcell.KeyCtrlA + 1),
|
||||
Key: keyseq.KeyType(key - tcell.KeyCtrlSpace),
|
||||
Ch: 0,
|
||||
Mod: mod,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,6 +538,62 @@ func TestTcellEventToEventCtrlKeysStripModCtrl(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestTcellEventToEventCtrlSpace verifies that Ctrl+Space is correctly
|
||||
// converted to KeyCtrlSpace (0x00) regardless of how the terminal reports it.
|
||||
//
|
||||
// Traditional terminals send NUL (0x00); tcell's input handler
|
||||
// delivers this as KeyCtrlSpace(64) with ModCtrl.
|
||||
// The KeyCtrlSpace..KeyCtrlZ path handles this.
|
||||
//
|
||||
// CSI u / enhanced terminals report Ctrl+Space as KeyRune with rune=' '
|
||||
// and ModCtrl. This must also produce Key=KeyCtrlSpace, Mod=ModNone
|
||||
// so that the ToggleSelectionAndSelectNext action fires correctly.
|
||||
func TestTcellEventToEventCtrlSpace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
tcellEv *tcell.EventKey
|
||||
wantKey keyseq.KeyType
|
||||
wantCh rune
|
||||
wantMod keyseq.ModifierKey
|
||||
}{
|
||||
{
|
||||
// Traditional terminal: NUL byte (0x00).
|
||||
// tcell's input handler calls
|
||||
// NewEventKey(KeyCtrlSpace+Key(r), 0, ModCtrl)
|
||||
// which yields key=KeyCtrlSpace(64), mod=ModCtrl.
|
||||
// The KeyCtrlSpace..KeyCtrlZ path strips ModCtrl and
|
||||
// maps to keyseq.KeyCtrlSpace(0x00).
|
||||
name: "traditional terminal: NUL byte via KeyCtrlSpace+ModCtrl",
|
||||
tcellEv: tcell.NewEventKey(tcell.KeyCtrlSpace, 0, tcell.ModCtrl),
|
||||
wantKey: keyseq.KeyCtrlSpace,
|
||||
wantCh: 0,
|
||||
wantMod: keyseq.ModNone,
|
||||
},
|
||||
{
|
||||
// CSI u / enhanced terminal: Ctrl+Space reported as
|
||||
// KeyRune with rune=' ' and ModCtrl.
|
||||
name: "CSI u terminal: Ctrl+Space as rune with ModCtrl",
|
||||
tcellEv: tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModCtrl),
|
||||
wantKey: keyseq.KeyCtrlSpace,
|
||||
wantCh: 0,
|
||||
wantMod: keyseq.ModNone,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := tcellEventToEvent(tt.tcellEv)
|
||||
require.Equal(t, EventKey, got.Type, "event type")
|
||||
require.Equal(t, tt.wantKey, got.Key, "key")
|
||||
require.Equal(t, tt.wantCh, got.Ch, "ch")
|
||||
require.Equal(t, tt.wantMod, got.Mod, "modifier")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestTcellEventToEventCtrlWithAltPreservesAlt verifies that Ctrl+Alt
|
||||
// combinations strip ModCtrl but preserve ModAlt.
|
||||
func TestTcellEventToEventCtrlWithAltPreservesAlt(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue