2021-10-12 09:38:08 -04:00
|
|
|
package tea
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2022-09-27 11:42:36 -04:00
|
|
|
"fmt"
|
2021-10-12 09:38:08 -04:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestKeyString(t *testing.T) {
|
|
|
|
t.Run("alt+space", func(t *testing.T) {
|
|
|
|
if got := KeyMsg(Key{
|
2022-05-13 13:24:16 -04:00
|
|
|
Type: KeySpace,
|
|
|
|
Alt: true,
|
2022-04-12 11:14:35 -04:00
|
|
|
}).String(); got != "alt+ " {
|
|
|
|
t.Fatalf(`expected a "alt+ ", got %q`, got)
|
2021-10-12 09:38:08 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("runes", func(t *testing.T) {
|
|
|
|
if got := KeyMsg(Key{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'a'},
|
|
|
|
}).String(); got != "a" {
|
|
|
|
t.Fatalf(`expected an "a", got %q`, got)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("invalid", func(t *testing.T) {
|
|
|
|
if got := KeyMsg(Key{
|
|
|
|
Type: KeyType(99999),
|
|
|
|
}).String(); got != "" {
|
|
|
|
t.Fatalf(`expected a "", got %q`, got)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKeyTypeString(t *testing.T) {
|
|
|
|
t.Run("space", func(t *testing.T) {
|
2022-05-13 13:24:16 -04:00
|
|
|
if got := KeySpace.String(); got != " " {
|
2022-04-12 11:14:35 -04:00
|
|
|
t.Fatalf(`expected a " ", got %q`, got)
|
2021-10-12 09:38:08 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("invalid", func(t *testing.T) {
|
|
|
|
if got := KeyType(99999).String(); got != "" {
|
|
|
|
t.Fatalf(`expected a "", got %q`, got)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadInput(t *testing.T) {
|
2022-05-28 20:30:29 -04:00
|
|
|
type test struct {
|
2022-09-27 11:42:36 -04:00
|
|
|
keyname string
|
|
|
|
in []byte
|
|
|
|
out []Msg
|
2022-05-28 20:30:29 -04:00
|
|
|
}
|
2022-09-27 11:42:36 -04:00
|
|
|
for i, td := range []test{
|
|
|
|
{"a",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{'a'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'a'},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{" ",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{' '},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeySpace,
|
|
|
|
Runes: []rune{' '},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"ctrl+a",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{byte(keySOH)},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyCtrlA,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"alt+a",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{byte(0x1b), 'a'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Alt: true,
|
|
|
|
Runes: []rune{'a'},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"abcd",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{'a', 'b', 'c', 'd'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'a'},
|
|
|
|
},
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'b'},
|
|
|
|
},
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'c'},
|
|
|
|
},
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyRunes,
|
|
|
|
Runes: []rune{'d'},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"up",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte("\x1b[A"),
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyUp,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"wheel up",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{'\x1b', '[', 'M', byte(32) + 0b0100_0000, byte(65), byte(49)},
|
|
|
|
[]Msg{
|
|
|
|
MouseMsg{
|
|
|
|
Type: MouseWheelUp,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"shift+tab",
|
2022-05-28 20:30:29 -04:00
|
|
|
[]byte{'\x1b', '[', 'Z'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyShiftTab,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"alt+enter",
|
2022-08-29 05:52:25 -04:00
|
|
|
[]byte{'\x1b', '\r'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyEnter,
|
|
|
|
Alt: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-10-07 08:48:42 -04:00
|
|
|
{"insert",
|
|
|
|
[]byte{'\x1b', '[', '2', '~'},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyInsert,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"alt+ctrl+a",
|
2022-08-29 05:52:25 -04:00
|
|
|
[]byte{'\x1b', byte(keySOH)},
|
|
|
|
[]Msg{
|
|
|
|
KeyMsg{
|
|
|
|
Type: KeyCtrlA,
|
|
|
|
Alt: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
{"unrecognized CSI",
|
2022-09-27 11:29:44 -04:00
|
|
|
[]byte{'\x1b', '[', '-', '-', '-', '-', 'X'},
|
|
|
|
[]Msg{},
|
|
|
|
},
|
2022-09-27 11:42:36 -04:00
|
|
|
// Powershell sequences.
|
|
|
|
{"up",
|
|
|
|
[]byte{'\x1b', 'O', 'A'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyUp}},
|
|
|
|
},
|
|
|
|
{"down",
|
|
|
|
[]byte{'\x1b', 'O', 'B'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyDown}},
|
|
|
|
},
|
|
|
|
{"right",
|
|
|
|
[]byte{'\x1b', 'O', 'C'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyRight}},
|
|
|
|
},
|
|
|
|
{"left",
|
|
|
|
[]byte{'\x1b', 'O', 'D'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyLeft}},
|
|
|
|
},
|
|
|
|
{"alt+enter",
|
|
|
|
[]byte{'\x1b', '\x0d'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyEnter, Alt: true}},
|
|
|
|
},
|
|
|
|
{"alt+backspace",
|
|
|
|
[]byte{'\x1b', '\x7f'},
|
|
|
|
[]Msg{KeyMsg{Type: KeyBackspace, Alt: true}},
|
|
|
|
},
|
2021-10-12 09:38:08 -04:00
|
|
|
} {
|
2022-09-27 11:42:36 -04:00
|
|
|
t.Run(fmt.Sprintf("%d: %s", i, td.keyname), func(t *testing.T) {
|
2022-05-28 20:30:29 -04:00
|
|
|
msgs, err := readInputs(bytes.NewReader(td.in))
|
2021-10-12 09:38:08 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %v", err)
|
|
|
|
}
|
2022-05-28 20:30:29 -04:00
|
|
|
if len(msgs) != len(td.out) {
|
|
|
|
t.Fatalf("unexpected message list length")
|
2022-02-02 22:14:49 -05:00
|
|
|
}
|
|
|
|
|
2022-05-28 20:30:29 -04:00
|
|
|
if len(msgs) == 1 {
|
2022-09-27 11:42:36 -04:00
|
|
|
if m, ok := msgs[0].(KeyMsg); ok && m.String() != td.keyname {
|
|
|
|
t.Fatalf(`expected a keymsg %q, got %q`, td.keyname, m)
|
2022-05-28 20:30:29 -04:00
|
|
|
}
|
2021-10-12 09:38:08 -04:00
|
|
|
}
|
2022-05-28 20:30:29 -04:00
|
|
|
|
|
|
|
for i, v := range msgs {
|
|
|
|
if m, ok := v.(KeyMsg); ok &&
|
|
|
|
m.String() != td.out[i].(KeyMsg).String() {
|
|
|
|
t.Fatalf(`expected a keymsg %q, got %q`, td.out[i].(KeyMsg), m)
|
|
|
|
}
|
|
|
|
if m, ok := v.(MouseMsg); ok &&
|
2022-09-27 11:42:36 -04:00
|
|
|
(mouseEventTypes[m.Type] != td.keyname || m.Type != td.out[i].(MouseMsg).Type) {
|
2022-05-28 20:30:29 -04:00
|
|
|
t.Fatalf(`expected a mousemsg %q, got %q`,
|
2022-09-27 11:42:36 -04:00
|
|
|
td.keyname,
|
2022-05-28 20:30:29 -04:00
|
|
|
mouseEventTypes[td.out[i].(MouseMsg).Type])
|
|
|
|
}
|
2021-10-12 09:38:08 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|