1package keys
2
3import (
4 "testing"
5
6 "github.com/stretchr/testify/require"
7)
8
9func TestScanEscape(t *testing.T) {
10 paste := "\x1b[200~\x1bj\x1b[1;3A\x1b[201~"
11 tests := []struct {
12 name string
13 in string
14 kind escKind
15 raw string
16 rune rune
17 arrow byte
18 }{
19 {name: "lone esc", in: "\x1b", kind: escIncomplete, raw: "\x1b"},
20 {name: "alt letter", in: "\x1bj", kind: escAltRune, raw: "\x1bj", rune: 'j'},
21 {name: "alt letter trailing bytes", in: "\x1bjxyz", kind: escAltRune, raw: "\x1bj", rune: 'j'},
22 {name: "alt space", in: "\x1b ", kind: escAltRune, raw: "\x1b ", rune: ' '},
23 {name: "alt utf8", in: "\x1bé", kind: escAltRune, raw: "\x1bé", rune: 'é'},
24 {name: "alt utf8 truncated", in: "\x1b\xc3", kind: escIncomplete, raw: "\x1b\xc3"},
25 {name: "alt invalid utf8", in: "\x1b\xc3X", kind: escBare, raw: "\x1b"},
26 {name: "alt stray continuation", in: "\x1b\xa9", kind: escBare, raw: "\x1b"},
27 {name: "double esc", in: "\x1b\x1b", kind: escAltRune, raw: "\x1b\x1b", rune: rune(ESC)},
28 {name: "alt arrow", in: "\x1b[1;3A", kind: escAltArrow, raw: "\x1b[1;3A", arrow: 'A'},
29 {name: "meta arrow trailing", in: "\x1b[1;9Dzz", kind: escAltArrow, raw: "\x1b[1;9D", arrow: 'D'},
30 {name: "alt arrow prefix 2", in: "\x1b[", kind: escIncomplete, raw: "\x1b["},
31 {name: "alt arrow prefix 3", in: "\x1b[1", kind: escIncomplete, raw: "\x1b[1"},
32 {name: "alt arrow prefix 5", in: "\x1b[1;3", kind: escIncomplete, raw: "\x1b[1;3"},
33 {name: "alt arrow wrong final", in: "\x1b[1;3E", kind: escControlPrefix, raw: "\x1b[", rune: '['},
34 {name: "ctrl arrow", in: "\x1b[1;5A", kind: escControlPrefix, raw: "\x1b[", rune: '['},
35 {name: "bare arrow", in: "\x1b[A", kind: escControlPrefix, raw: "\x1b[", rune: '['},
36 {name: "ss3", in: "\x1bOP", kind: escControlPrefix, raw: "\x1bO", rune: 'O'},
37 {name: "paste complete", in: paste + "tail", kind: escPaste, raw: paste},
38 {name: "paste unterminated", in: "\x1b[200~hello", kind: escControlPrefix, raw: "\x1b[", rune: '['},
39 }
40 for _, tt := range tests {
41 t.Run(tt.name, func(t *testing.T) {
42 got := scanEscape([]byte(tt.in), false)
43 require.Equal(t, tt.kind, got.kind)
44 require.Equal(t, []byte(tt.raw), got.raw)
45 require.Equal(t, tt.rune, got.rune)
46 require.Equal(t, tt.arrow, got.arrow)
47 })
48 }
49}
50
51func TestScanEscapeEveryAltArrowPrefixIsIncomplete(t *testing.T) {
52 for _, full := range []string{"\x1b[1;3A", "\x1b[1;9C"} {
53 for n := 1; n < len(full); n++ {
54 got := scanEscape([]byte(full[:n]), false)
55 require.Equal(t, escIncomplete, got.kind, "prefix %q", full[:n])
56 require.Equal(t, []byte(full[:n]), got.raw)
57 }
58 }
59}