src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/ui/key_test.go (about)

     1  package ui
     2  
     3  import (
     4  	"testing"
     5  
     6  	"src.elv.sh/pkg/eval/vals"
     7  	"src.elv.sh/pkg/persistent/hash"
     8  )
     9  
    10  var KTests = []struct {
    11  	k1 Key
    12  	k2 Key
    13  }{
    14  	{K('a'), Key{'a', 0}},
    15  	{K('a', Alt), Key{'a', Alt}},
    16  	{K('a', Alt, Ctrl), Key{'a', Alt | Ctrl}},
    17  }
    18  
    19  func TestK(t *testing.T) {
    20  	for _, test := range KTests {
    21  		if test.k1 != test.k2 {
    22  			t.Errorf("%v != %v", test.k1, test.k2)
    23  		}
    24  	}
    25  }
    26  
    27  func TestKeyAsElvishValue(t *testing.T) {
    28  	vals.TestValue(t, K('a')).
    29  		Kind("edit:key").
    30  		Hash(hash.DJB('a', 0)).
    31  		Repr("(edit:key a)").
    32  		Equal(K('a')).
    33  		NotEqual(K('A'), K('a', Alt))
    34  
    35  	vals.TestValue(t, K('a', Alt)).Repr("(edit:key Alt-a)")
    36  	vals.TestValue(t, K('a', Ctrl, Alt, Shift)).Repr("(edit:key Ctrl-Alt-Shift-a)")
    37  
    38  	vals.TestValue(t, K('\t')).Repr("(edit:key Tab)")
    39  	vals.TestValue(t, K(F1)).Repr("(edit:key F1)")
    40  	vals.TestValue(t, K(-1)).Repr("(edit:key '(bad function key -1)')")
    41  	vals.TestValue(t, K(-2000)).Repr("(edit:key '(bad function key -2000)')")
    42  }
    43  
    44  var parseKeyTests = []struct {
    45  	s       string
    46  	wantKey Key
    47  	wantErr string
    48  }{
    49  	{s: "x", wantKey: K('x')},
    50  	{s: "Tab", wantKey: K(Tab)},
    51  	{s: "F1", wantKey: K(F1)},
    52  
    53  	// Alt- keys are case-sensitive.
    54  	{s: "A-x", wantKey: Key{'x', Alt}},
    55  	{s: "A-X", wantKey: Key{'X', Alt}},
    56  
    57  	// Ctrl- keys are case-insensitive.
    58  	{s: "C-x", wantKey: Key{'X', Ctrl}},
    59  	{s: "C-X", wantKey: Key{'X', Ctrl}},
    60  
    61  	// Literal control chars are equivalent to the preferred Ctrl-<key>
    62  	// formulation.
    63  	{s: "\033", wantKey: Key{'[', Ctrl}},
    64  
    65  	// + is the same as -.
    66  	{s: "C+X", wantKey: Key{'X', Ctrl}},
    67  
    68  	// Full names and alternative names can also be used.
    69  	{s: "M-x", wantKey: Key{'x', Alt}},
    70  	{s: "Meta-x", wantKey: Key{'x', Alt}},
    71  
    72  	// Multiple modifiers can appear in any order and with alternative
    73  	// separator chars.
    74  	{s: "Alt-Ctrl+Delete", wantKey: Key{Delete, Alt | Ctrl}},
    75  	{s: "Ctrl+Alt-Delete", wantKey: Key{Delete, Alt | Ctrl}},
    76  
    77  	// Confirm alternative symbolic keys are turned into the canonical form.
    78  	{s: "\t", wantKey: K(Tab)},       // literal tab is normalized to Tab
    79  	{s: "\n", wantKey: K(Enter)},     // literal newline is normalized to Enter
    80  	{s: "Ctrl-I", wantKey: K(Tab)},   // Ctrl-I is normalized to Tab
    81  	{s: "Ctrl-J", wantKey: K(Enter)}, // Ctrl-J is normalized to Enter
    82  	{s: "Alt-\t", wantKey: Key{Tab, Alt}},
    83  	{s: "\x7F", wantKey: K(Backspace)},
    84  
    85  	// Errors.
    86  	{s: "F123", wantErr: "bad key: F123"},
    87  	{s: "Super-X", wantErr: "bad modifier: Super"},
    88  	{s: "a-x", wantErr: "bad modifier: a"},
    89  	{s: "Ctrl-\t", wantErr: `Ctrl modifier with literal control char: '\t'`},
    90  }
    91  
    92  func TestParseKey(t *testing.T) {
    93  	for _, test := range parseKeyTests {
    94  		key, err := ParseKey(test.s)
    95  		if key != test.wantKey {
    96  			t.Errorf("ParseKey(%q) => %v, want %v", test.s, key, test.wantKey)
    97  		}
    98  		if test.wantErr == "" {
    99  			if err != nil {
   100  				t.Errorf("ParseKey(%q) => error %v, want nil", test.s, err)
   101  			}
   102  		} else {
   103  			if err == nil || err.Error() != test.wantErr {
   104  				t.Errorf("ParseKey(%q) => error %v, want error with message %q",
   105  					test.s, err, test.wantErr)
   106  			}
   107  		}
   108  	}
   109  }