2017-06-01 06:47:42 +08:00
|
|
|
package ui
|
|
|
|
|
2020-03-31 12:55:49 +08:00
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2021-01-27 09:28:38 +08:00
|
|
|
"src.elv.sh/pkg/eval/vals"
|
2021-05-04 05:17:46 +08:00
|
|
|
"src.elv.sh/pkg/persistent/hash"
|
2020-03-31 12:55:49 +08:00
|
|
|
)
|
|
|
|
|
2021-03-15 11:42:43 +08:00
|
|
|
var KTests = []struct {
|
2020-03-31 12:55:49 +08:00
|
|
|
k1 Key
|
|
|
|
k2 Key
|
|
|
|
}{
|
|
|
|
{K('a'), Key{'a', 0}},
|
|
|
|
{K('a', Alt), Key{'a', Alt}},
|
|
|
|
{K('a', Alt, Ctrl), Key{'a', Alt | Ctrl}},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestK(t *testing.T) {
|
2021-03-15 11:42:43 +08:00
|
|
|
for _, test := range KTests {
|
2020-03-31 12:55:49 +08:00
|
|
|
if test.k1 != test.k2 {
|
|
|
|
t.Errorf("%v != %v", test.k1, test.k2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKeyAsElvishValue(t *testing.T) {
|
|
|
|
vals.TestValue(t, K('a')).
|
|
|
|
Kind("edit:key").
|
|
|
|
Hash(hash.DJB('a', 0)).
|
|
|
|
Repr("(edit:key a)").
|
|
|
|
Equal(K('a')).
|
|
|
|
NotEqual(K('A'), K('a', Alt))
|
|
|
|
|
|
|
|
vals.TestValue(t, K('a', Alt)).Repr("(edit:key Alt-a)")
|
|
|
|
vals.TestValue(t, K('a', Ctrl, Alt, Shift)).Repr("(edit:key Ctrl-Alt-Shift-a)")
|
|
|
|
|
|
|
|
vals.TestValue(t, K('\t')).Repr("(edit:key Tab)")
|
|
|
|
vals.TestValue(t, K(F1)).Repr("(edit:key F1)")
|
2020-04-01 05:58:17 +08:00
|
|
|
vals.TestValue(t, K(-1)).Repr("(edit:key '(bad function key -1)')")
|
|
|
|
vals.TestValue(t, K(-2000)).Repr("(edit:key '(bad function key -2000)')")
|
2020-03-31 12:55:49 +08:00
|
|
|
}
|
2017-06-01 06:47:42 +08:00
|
|
|
|
|
|
|
var parseKeyTests = []struct {
|
|
|
|
s string
|
|
|
|
wantKey Key
|
2020-04-01 05:58:17 +08:00
|
|
|
wantErr string
|
2017-06-01 06:47:42 +08:00
|
|
|
}{
|
2020-04-01 05:58:17 +08:00
|
|
|
{s: "x", wantKey: K('x')},
|
|
|
|
{s: "Tab", wantKey: K(Tab)},
|
|
|
|
{s: "F1", wantKey: K(F1)},
|
|
|
|
|
2017-06-01 06:47:42 +08:00
|
|
|
// Alt- keys are case-sensitive.
|
2020-10-21 12:49:47 +08:00
|
|
|
{s: "A-x", wantKey: Key{'x', Alt}},
|
|
|
|
{s: "A-X", wantKey: Key{'X', Alt}},
|
2017-06-01 06:47:42 +08:00
|
|
|
|
|
|
|
// Ctrl- keys are case-insensitive.
|
2020-04-01 05:58:17 +08:00
|
|
|
{s: "C-x", wantKey: Key{'X', Ctrl}},
|
|
|
|
{s: "C-X", wantKey: Key{'X', Ctrl}},
|
2017-06-01 06:47:42 +08:00
|
|
|
|
2020-12-25 08:43:57 +08:00
|
|
|
// Literal control chars are equivalent to the preferred Ctrl-<key>
|
|
|
|
// formulation.
|
2020-11-26 10:29:10 +08:00
|
|
|
{s: "\033", wantKey: Key{'[', Ctrl}},
|
|
|
|
|
2017-06-01 06:47:42 +08:00
|
|
|
// + is the same as -.
|
2020-04-01 05:58:17 +08:00
|
|
|
{s: "C+X", wantKey: Key{'X', Ctrl}},
|
2017-06-01 06:47:42 +08:00
|
|
|
|
|
|
|
// Full names and alternative names can also be used.
|
2020-04-01 05:58:17 +08:00
|
|
|
{s: "M-x", wantKey: Key{'x', Alt}},
|
|
|
|
{s: "Meta-x", wantKey: Key{'x', Alt}},
|
2017-06-01 06:47:42 +08:00
|
|
|
|
2020-11-12 12:57:13 +08:00
|
|
|
// Multiple modifiers can appear in any order and with alternative
|
|
|
|
// separator chars.
|
2020-10-21 12:49:47 +08:00
|
|
|
{s: "Alt-Ctrl+Delete", wantKey: Key{Delete, Alt | Ctrl}},
|
|
|
|
{s: "Ctrl+Alt-Delete", wantKey: Key{Delete, Alt | Ctrl}},
|
2020-03-31 12:55:49 +08:00
|
|
|
|
2020-11-12 12:57:13 +08:00
|
|
|
// Confirm alternative symbolic keys are turned into the canonical form.
|
2020-12-25 08:43:57 +08:00
|
|
|
{s: "\t", wantKey: K(Tab)}, // literal tab is normalized to Tab
|
|
|
|
{s: "\n", wantKey: K(Enter)}, // literal newline is normalized to Enter
|
|
|
|
{s: "Ctrl-I", wantKey: K(Tab)}, // Ctrl-I is normalized to Tab
|
|
|
|
{s: "Ctrl-J", wantKey: K(Enter)}, // Ctrl-J is normalized to Enter
|
|
|
|
{s: "Alt-\t", wantKey: Key{Tab, Alt}},
|
|
|
|
{s: "\x7F", wantKey: K(Backspace)},
|
2020-04-01 05:58:17 +08:00
|
|
|
|
|
|
|
// Errors.
|
|
|
|
{s: "F123", wantErr: "bad key: F123"},
|
2020-10-21 12:49:47 +08:00
|
|
|
{s: "Super-X", wantErr: "bad modifier: Super"},
|
|
|
|
{s: "a-x", wantErr: "bad modifier: a"},
|
2020-11-26 10:29:10 +08:00
|
|
|
{s: "Ctrl-\t", wantErr: `Ctrl modifier with literal control char: '\t'`},
|
2017-06-01 06:47:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseKey(t *testing.T) {
|
|
|
|
for _, test := range parseKeyTests {
|
2020-04-01 06:05:41 +08:00
|
|
|
key, err := ParseKey(test.s)
|
2017-06-01 06:47:42 +08:00
|
|
|
if key != test.wantKey {
|
|
|
|
t.Errorf("ParseKey(%q) => %v, want %v", test.s, key, test.wantKey)
|
|
|
|
}
|
2020-04-01 05:58:17 +08:00
|
|
|
if test.wantErr == "" {
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("ParseKey(%q) => error %v, want nil", test.s, err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err == nil || err.Error() != test.wantErr {
|
|
|
|
t.Errorf("ParseKey(%q) => error %v, want error with message %q",
|
|
|
|
test.s, err, test.wantErr)
|
|
|
|
}
|
2017-06-01 06:47:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|