mirror of
https://github.com/jixishi/SerialTerminalForWindowsTerminal.git
synced 2026-06-15 16:42:46 +00:00
fix: insert CSI u handler into model.go + add tui tests
The previous commit defined parseCSIuBytes but failed to insert the handler into Update(). Now properly inserted before the textinput fallback. Add 10 test cases for parseCSIuBytes covering ctrl+alt+f/c/ m/p/h, ctrl+shift+c, alt+c, and invalid sequences. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -240,6 +240,28 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handle CSI u sequences that bubbletea does not parse into KeyMsg
|
||||||
|
if b, ok := msg.([]byte); ok {
|
||||||
|
if key, ok2 := parseCSIuBytes(b); ok2 {
|
||||||
|
keyStr := strings.ToLower(key)
|
||||||
|
if m.showModal {
|
||||||
|
last := rune(key[len(key)-1])
|
||||||
|
fake := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{last}, Alt: strings.Contains(key, "alt+")}
|
||||||
|
if handled, _ := m.handleModalKey(fake); handled {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if keyStr == normalizeHotkeyPrefix(m.App.Cfg().HotkeyMod)+"+c" {
|
||||||
|
m.App.Close()
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
if handleLocalHotkey(m, keyStr) {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
m.input, cmd = m.input.Update(msg)
|
m.input, cmd = m.input.Update(msg)
|
||||||
return m, cmd
|
return m, cmd
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestParseCSIuBytes(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
seq []byte
|
||||||
|
want string
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{name: "ctrl+alt+f", seq: []byte{0x1b, '[', '1', '0', '2', ';', '6', 'u'}, want: "ctrl+alt+f", ok: true},
|
||||||
|
{name: "ctrl+alt+c", seq: []byte{0x1b, '[', '9', '9', ';', '6', 'u'}, want: "ctrl+alt+c", ok: true},
|
||||||
|
{name: "ctrl+alt+m", seq: []byte{0x1b, '[', '1', '0', '9', ';', '6', 'u'}, want: "ctrl+alt+m", ok: true},
|
||||||
|
{name: "ctrl+alt+p", seq: []byte{0x1b, '[', '1', '1', '2', ';', '6', 'u'}, want: "ctrl+alt+p", ok: true},
|
||||||
|
{name: "ctrl+alt+h", seq: []byte{0x1b, '[', '1', '0', '4', ';', '6', 'u'}, want: "ctrl+alt+h", ok: true},
|
||||||
|
{name: "ctrl+shift+c", seq: []byte{0x1b, '[', '9', '9', ';', '5', 'u'}, want: "ctrl+shift+c", ok: true},
|
||||||
|
{name: "alt+c (no ctrl)", seq: []byte{0x1b, '[', '9', '9', ';', '2', 'u'}, want: "alt+c", ok: true},
|
||||||
|
{name: "plain c", seq: []byte{0x1b, '[', '9', '9', ';', '0', 'u'}, want: "c", ok: true},
|
||||||
|
{name: "not CSI u", seq: []byte{0x1b, '[', 'A'}, want: "", ok: false},
|
||||||
|
{name: "empty", seq: []byte{}, want: "", ok: false},
|
||||||
|
{name: "no escape", seq: []byte("hello"), want: "", ok: false},
|
||||||
|
{name: "ESC [ A (arrow up)", seq: []byte{0x1b, '[', 'A'}, want: "", ok: false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, ok := parseCSIuBytes(tt.seq)
|
||||||
|
if ok != tt.ok || got != tt.want {
|
||||||
|
t.Fatalf("parseCSIuBytes(%v): got=(%q,%v) want=(%q,%v)", tt.seq, got, ok, tt.want, tt.ok)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user