turbo-editors/turbo-corepublic Fork 0
v0.9.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 28d5985 · on v0.9.0 · k33g · 13h ago
keys_test.go · 150 lines · 4.3 KBGo Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package terminal

import (
	"testing"

	"github.com/gdamore/tcell/v2"
)

func TestEncodePrintableCharacters(t *testing.T) {
	tests := []struct {
		name string
		rune rune
		mods tcell.ModMask
		want string
	}{
		{"a letter", 'a', tcell.ModNone, "a"},
		{"a space", ' ', tcell.ModNone, " "},
		{"an accented letter is UTF-8", 'é', tcell.ModNone, "é"},
		{"Alt prefixes an escape", 'b', tcell.ModAlt, "\x1bb"},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := Encode(tcell.NewEventKey(tcell.KeyRune, tc.rune, tc.mods), false)
			if string(got) != tc.want {
				t.Errorf("Encode() = %q, want %q", got, tc.want)
			}
		})
	}
}

func TestEncodeNamedKeys(t *testing.T) {
	tests := []struct {
		key  tcell.Key
		want string
	}{
		{tcell.KeyEnter, "\r"},
		{tcell.KeyTab, "\t"},
		{tcell.KeyEscape, "\x1b"},
		{tcell.KeyBacktab, "\x1b[Z"},
		{tcell.KeyDelete, "\x1b[3~"},
		{tcell.KeyInsert, "\x1b[2~"},
		{tcell.KeyPgUp, "\x1b[5~"},
		{tcell.KeyPgDn, "\x1b[6~"},
		{tcell.KeyF1, "\x1bOP"},
		{tcell.KeyF5, "\x1b[15~"},
		{tcell.KeyF12, "\x1b[24~"},
	}

	for _, tc := range tests {
		got := Encode(tcell.NewEventKey(tc.key, 0, tcell.ModNone), false)
		if string(got) != tc.want {
			t.Errorf("Encode(%v) = %q, want %q", tc.key, got, tc.want)
		}
	}
}

func TestEncodeCursorKeysFollowTheModeTheProgramAskedFor(t *testing.T) {
	// This is the most visible thing an emulator can get wrong: the arrow keys
	// inside vim or at a readline prompt.
	tests := []struct {
		key            tcell.Key
		normal, appMod string
	}{
		{tcell.KeyUp, "\x1b[A", "\x1bOA"},
		{tcell.KeyDown, "\x1b[B", "\x1bOB"},
		{tcell.KeyRight, "\x1b[C", "\x1bOC"},
		{tcell.KeyLeft, "\x1b[D", "\x1bOD"},
		{tcell.KeyHome, "\x1b[H", "\x1bOH"},
		{tcell.KeyEnd, "\x1b[F", "\x1bOF"},
	}

	for _, tc := range tests {
		if got := Encode(tcell.NewEventKey(tc.key, 0, tcell.ModNone), false); string(got) != tc.normal {
			t.Errorf("Encode(%v) = %q, want %q", tc.key, got, tc.normal)
		}
		if got := Encode(tcell.NewEventKey(tc.key, 0, tcell.ModNone), true); string(got) != tc.appMod {
			t.Errorf("Encode(%v) in application mode = %q, want %q", tc.key, got, tc.appMod)
		}
	}
}

func TestEncodeControlKeys(t *testing.T) {
	// tcell's value for a control key *is* the byte a terminal expects.
	tests := []struct {
		name string
		key  tcell.Key
		want byte
	}{
		{"Ctrl-A", tcell.KeyCtrlA, 0x01},
		{"Ctrl-C interrupts", tcell.KeyCtrlC, 0x03},
		{"Ctrl-D ends the input", tcell.KeyCtrlD, 0x04},
		{"Ctrl-Z suspends", tcell.KeyCtrlZ, 0x1a},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := Encode(tcell.NewEventKey(tc.key, 0, tcell.ModCtrl), false)
			if len(got) != 1 || got[0] != tc.want {
				t.Errorf("Encode() = %q, want the single byte %#02x", got, tc.want)
			}
		})
	}
}

func TestBackspaceSendsDelete(t *testing.T) {
	// tcell posts both 0x08 and 0x7f as KeyBackspace, so Ctrl-H and the
	// backspace key cannot be told apart here. DEL is what a modern terminal
	// sends for the key people actually press.
	for _, key := range []tcell.Key{tcell.KeyBackspace, tcell.KeyBackspace2} {
		if got := Encode(tcell.NewEventKey(key, 0, tcell.ModNone), false); string(got) != "\x7f" {
			t.Errorf("Encode(%v) = %q, want DEL", key, got)
		}
	}
}

func TestControlKeysUseTcellsOwnOffset(t *testing.T) {
	// A real terminal byte of 0x03 reaches tcell as KeyCtrlSpace+3. Encoding
	// from the raw value instead would send nothing at all for every Ctrl-key,
	// silently.
	if got := int(tcell.KeyCtrlSpace); got != 64 {
		t.Fatalf("tcell.KeyCtrlSpace = %d, want 64 — this test's premise has changed", got)
	}

	for control := byte(0); control < 32; control++ {
		key := tcell.KeyCtrlSpace + tcell.Key(control)
		if _, named := namedKeys[key]; named {
			continue
		}

		got := Encode(tcell.NewEventKey(key, 0, tcell.ModCtrl), false)
		if len(got) != 1 || got[0] != control {
			t.Errorf("Encode(%v) = %q, want the single byte %#02x", key, got, control)
		}
	}
}

func TestAltWithAControlKeyPrefixesAnEscape(t *testing.T) {
	got := Encode(tcell.NewEventKey(tcell.KeyCtrlC, 0, tcell.ModCtrl|tcell.ModAlt), false)

	if string(got) != "\x1b\x03" {
		t.Errorf("Encode() = %q, want an escape then the control byte", got)
	}
}

func TestAKeyWithNoTerminalMeaningEncodesToNothing(t *testing.T) {
	if got := Encode(tcell.NewEventKey(tcell.KeyF64, 0, tcell.ModNone), false); len(got) != 0 {
		t.Errorf("Encode() = %q, want nothing to send", got)
	}
}