// Copyright 2026 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tests
import (
"slices"
"testing"
"github.com/gdamore/tcell/v3/vt"
"github.com/gdamore/tcell/v3/vt/layouts/us"
)
func TestGetLayout(t *testing.T) {
l := vt.GetLayout("US International")
if l == nil {
t.Fatalf("no keyboard layout found")
}
if l != us.UsInternational {
t.Errorf("got the wrong layout: %s", l.Name)
}
layouts := vt.Layouts()
VerifyF(t, slices.Contains(layouts, "US International"), "layout not present")
}
func TestUsAltGr(t *testing.T) {
term := vt.NewMockTerm(vt.MockOptSize{X: 8, Y: 4})
defer MustClose(t, term)
term.SetLayout(vt.GetLayout("US International"))
MustStart(t, term)
cases := []struct {
name string
keys []vt.Key
want string
}{
{"AltGr-0", []vt.Key{vt.KeyRAlt, vt.Key0}, "’"},
{"AltGr-1", []vt.Key{vt.KeyRAlt, vt.Key1}, "¡"},
{"AltGr-2", []vt.Key{vt.KeyRAlt, vt.Key2}, "²"},
{"AltGr-3", []vt.Key{vt.KeyRAlt, vt.Key3}, "³"},
{"AltGr-4", []vt.Key{vt.KeyRAlt, vt.Key4}, "¤"},
{"AltGr-5", []vt.Key{vt.KeyRAlt, vt.Key5}, "€"},
{"AltGr-6", []vt.Key{vt.KeyRAlt, vt.Key6}, "¼"},
{"AltGr-7", []vt.Key{vt.KeyRAlt, vt.Key7}, "½"},
{"AltGr-8", []vt.Key{vt.KeyRAlt, vt.Key8}, "¾"},
{"AltGr-9", []vt.Key{vt.KeyRAlt, vt.Key9}, "‘"},
{"AltGr-A", []vt.Key{vt.KeyRAlt, vt.KeyA}, "á"},
{"AltGr-C", []vt.Key{vt.KeyRAlt, vt.KeyC}, "©"},
{"AltGr-D", []vt.Key{vt.KeyRAlt, vt.KeyD}, "ð"},
{"AltGr-E", []vt.Key{vt.KeyRAlt, vt.KeyE}, "é"},
{"AltGr-I", []vt.Key{vt.KeyRAlt, vt.KeyI}, "í"},
{"AltGr-L", []vt.Key{vt.KeyRAlt, vt.KeyL}, "ø"},
{"AltGr-M", []vt.Key{vt.KeyRAlt, vt.KeyM}, "µ"},
{"AltGr-N", []vt.Key{vt.KeyRAlt, vt.KeyN}, "ñ"},
{"AltGr-O", []vt.Key{vt.KeyRAlt, vt.KeyO}, "ó"},
{"AltGr-P", []vt.Key{vt.KeyRAlt, vt.KeyP}, "ö"},
{"AltGr-Q", []vt.Key{vt.KeyRAlt, vt.KeyQ}, "ä"},
{"AltGr-R", []vt.Key{vt.KeyRAlt, vt.KeyR}, "®"},
{"AltGr-S", []vt.Key{vt.KeyRAlt, vt.KeyS}, "ß"},
{"AltGr-T", []vt.Key{vt.KeyRAlt, vt.KeyT}, "þ"},
{"AltGr-U", []vt.Key{vt.KeyRAlt, vt.KeyU}, "ú"},
{"AltGr-W", []vt.Key{vt.KeyRAlt, vt.KeyW}, "å"},
{"AltGr-Y", []vt.Key{vt.KeyRAlt, vt.KeyY}, "ü"},
{"AltGr-Z", []vt.Key{vt.KeyRAlt, vt.KeyZ}, "æ"},
{"AltGr-Semi", []vt.Key{vt.KeyRAlt, vt.KeySemi}, "¶"},
{"AltGr-Equal", []vt.Key{vt.KeyRAlt, vt.KeyEqual}, "×"},
{"AltGr-Comma", []vt.Key{vt.KeyRAlt, vt.KeyComma}, "ç"},
{"AltGr-Minus", []vt.Key{vt.KeyRAlt, vt.KeyMinus}, "¥"},
{"AltGr-Slash", []vt.Key{vt.KeyRAlt, vt.KeySlash}, "¿"},
{"AltGr-LBrace", []vt.Key{vt.KeyRAlt, vt.KeyLBrace}, "«"},
{"AltGr-Backslash", []vt.Key{vt.KeyRAlt, vt.KeyBackslash}, "¬"},
{"AltGr-RBrace", []vt.Key{vt.KeyRAlt, vt.KeyRBrace}, "»"},
{"AltGr-Quote", []vt.Key{vt.KeyRAlt, vt.KeyQuote}, "´"},
{"S-AltGr-0", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key0}, ""},
{"S-AltGr-1", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key1}, "¹"},
{"S-AltGr-2", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key2}, ""},
{"S-AltGr-3", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key3}, ""},
{"S-AltGr-4", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key4}, "£"},
{"S-AltGr-5", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key5}, ""},
{"S-AltGr-6", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key6}, ""},
{"S-AltGr-7", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key7}, ""},
{"S-AltGr-8", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key8}, ""},
{"S-AltGr-9", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.Key9}, ""},
{"S-AltGr-A", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyA}, "Á"},
{"S-AltGr-B", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyB}, ""},
{"S-AltGr-C", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyC}, "¢"},
{"S-AltGr-D", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyD}, "Ð"},
{"S-AltGr-E", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyE}, "É"},
{"S-AltGr-F", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyF}, ""},
{"S-AltGr-G", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyG}, ""},
{"S-AltGr-H", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyH}, ""},
{"S-AltGr-I", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyI}, "Í"},
{"S-AltGr-J", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyJ}, ""},
{"S-AltGr-K", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyK}, ""},
{"S-AltGr-L", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyL}, "Ø"},
{"S-AltGr-M", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyM}, ""},
{"S-AltGr-N", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyN}, "Ñ"},
{"S-AltGr-O", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyO}, "Ó"},
{"S-AltGr-P", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyP}, "Ö"},
{"S-AltGr-Q", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyQ}, "Ä"},
{"S-AltGr-R", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyR}, ""},
{"S-AltGr-S", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyS}, "§"},
{"S-AltGr-T", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyT}, "Þ"},
{"S-AltGr-U", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyU}, "Ú"},
{"S-AltGr-V", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyV}, ""},
{"S-AltGr-W", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyW}, "Å"},
{"S-AltGr-X", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyX}, ""},
{"S-AltGr-Y", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyY}, "Ü"},
{"S-AltGr-Z", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyZ}, "Æ"},
{"S-AltGr-Semi", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeySemi}, "°"},
{"S-AltGr-Equal", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyEqual}, "÷"},
{"S-AltGr-Comma", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyComma}, "Ç"},
{"S-AltGr-Minus", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyMinus}, ""},
{"S-AltGr-Slash", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeySlash}, ""},
{"S-AltGr-LBrace", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyLBrace}, ""},
{"S-AltGr-RBrace", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyRBrace}, ""},
{"S-AltGr-BackSlash", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyBackslash}, "¦"},
{"S-AltGr-Quote", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyQuote}, "¨"},
{"S-AltGr-IsoBackSlash", []vt.Key{vt.KeyRAlt, vt.KeyLShift, vt.KeyIsoBackSlash}, ""},
{"Alt-Ctrl-0", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key0}, "’"},
{"Alt-Ctrl-1", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key1}, "¡"},
{"Alt-Ctrl-2", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key2}, "²"},
{"Alt-Ctrl-3", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key3}, "³"},
{"Alt-Ctrl-4", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key4}, "¤"},
{"Alt-Ctrl-5", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key5}, "€"},
{"Alt-Ctrl-6", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key6}, "¼"},
{"Alt-Ctrl-7", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key7}, "½"},
{"Alt-Ctrl-8", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key8}, "¾"},
{"Alt-Ctrl-9", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.Key9}, "‘"},
{"Alt-Ctrl-A", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyA}, "á"},
{"Alt-Ctrl-C", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyC}, "©"},
{"Alt-Ctrl-D", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyD}, "ð"},
{"Alt-Ctrl-E", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyE}, "é"},
{"Alt-Ctrl-I", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyI}, "í"},
{"Alt-Ctrl-L", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyL}, "ø"},
{"Alt-Ctrl-M", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyM}, "µ"},
{"Alt-Ctrl-N", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyN}, "ñ"},
{"Alt-Ctrl-O", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyO}, "ó"},
{"Alt-Ctrl-P", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyP}, "ö"},
{"Alt-Ctrl-Q", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyQ}, "ä"},
{"Alt-Ctrl-R", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyR}, "®"},
{"Alt-Ctrl-S", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyS}, "ß"},
{"Alt-Ctrl-T", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyT}, "þ"},
{"Alt-Ctrl-U", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyU}, "ú"},
{"Alt-Ctrl-W", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyW}, "å"},
{"Alt-Ctrl-Y", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyY}, "ü"},
{"Alt-Ctrl-Z", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyZ}, "æ"},
{"Alt-Ctrl-Semi", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeySemi}, "¶"},
{"Alt-Ctrl-Equal", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyEqual}, "×"},
{"Alt-Ctrl-Comma", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyComma}, "ç"},
{"Alt-Ctrl-Minus", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyMinus}, "¥"},
{"Alt-Ctrl-Slash", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeySlash}, "¿"},
{"Alt-Ctrl-LBrace", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLBrace}, "«"},
{"Alt-Ctrl-Backslash", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyBackslash}, "¬"},
{"Alt-Ctrl-RBrace", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyRBrace}, "»"},
{"Alt-Ctrl-Quote", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyQuote}, "´"},
{"S-Alt-Ctrl-0", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key0}, ""},
{"S-Alt-Ctrl-1", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key1}, "¹"},
{"S-Alt-Ctrl-2", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key2}, ""},
{"S-Alt-Ctrl-3", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key3}, ""},
{"S-Alt-Ctrl-4", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key4}, "£"},
{"S-Alt-Ctrl-5", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key5}, ""},
{"S-Alt-Ctrl-6", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key6}, ""},
{"S-Alt-Ctrl-7", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key7}, ""},
{"S-Alt-Ctrl-8", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key8}, ""},
{"S-Alt-Ctrl-9", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.Key9}, ""},
{"S-Alt-Ctrl-A", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyA}, "Á"},
{"S-Alt-Ctrl-B", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyB}, ""},
{"S-Alt-Ctrl-C", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyC}, "¢"},
{"S-Alt-Ctrl-D", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyD}, "Ð"},
{"S-Alt-Ctrl-E", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyE}, "É"},
{"S-Alt-Ctrl-F", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyF}, ""},
{"S-Alt-Ctrl-G", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyG}, ""},
{"S-Alt-Ctrl-H", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyH}, ""},
{"S-Alt-Ctrl-I", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyI}, "Í"},
{"S-Alt-Ctrl-J", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyJ}, ""},
{"S-Alt-Ctrl-K", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyK}, ""},
{"S-Alt-Ctrl-L", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyL}, "Ø"},
{"S-Alt-Ctrl-M", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyM}, ""},
{"S-Alt-Ctrl-N", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyN}, "Ñ"},
{"S-Alt-Ctrl-O", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyO}, "Ó"},
{"S-Alt-Ctrl-P", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyP}, "Ö"},
{"S-Alt-Ctrl-Q", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyQ}, "Ä"},
{"S-Alt-Ctrl-R", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyR}, ""},
{"S-Alt-Ctrl-S", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyS}, "§"},
{"S-Alt-Ctrl-T", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyT}, "Þ"},
{"S-Alt-Ctrl-U", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyU}, "Ú"},
{"S-Alt-Ctrl-V", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyV}, ""},
{"S-Alt-Ctrl-W", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyW}, "Å"},
{"S-Alt-Ctrl-X", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyX}, ""},
{"S-Alt-Ctrl-Y", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyY}, "Ü"},
{"S-Alt-Ctrl-Z", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyZ}, "Æ"},
{"S-Alt-Ctrl-Semi", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeySemi}, "°"},
{"S-Alt-Ctrl-Equal", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyEqual}, "÷"},
{"S-Alt-Ctrl-Comma", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyComma}, "Ç"},
{"S-Alt-Ctrl-Minus", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyMinus}, ""},
{"S-Alt-Ctrl-Slash", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeySlash}, ""},
{"S-Alt-Ctrl-LBrace", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyLBrace}, ""},
{"S-Alt-Ctrl-RBrace", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyRBrace}, ""},
{"S-Alt-Ctrl-BackSlash", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyBackslash}, "¦"},
{"S-Alt-Ctrl-Quote", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyQuote}, "¨"},
{"S-Alt-Ctrl-IsoBackSlash", []vt.Key{vt.KeyLAlt, vt.KeyLCtrl, vt.KeyLShift, vt.KeyIsoBackSlash}, ""},
}
for i := range cases {
t.Run(cases[i].name, func(t *testing.T) {
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace) // add a vanilla space to force output if empty
CheckRead(t, term, cases[i].want+" ")
})
}
}
func TestDeadKeys(t *testing.T) {
term := vt.NewMockTerm(vt.MockOptSize{X: 8, Y: 4})
defer MustClose(t, term)
term.SetLayout(vt.GetLayout("US International"))
MustStart(t, term)
term.KeyTap(vt.KeyGrave)
term.KeyTap(vt.KeyA)
want := "à"
result := ReadF(t, term)
VerifyF(t, want == result, "wrong read %q != %q", result, want)
cases := []struct {
name string
keys []vt.Key
key []vt.Key
want string
}{
{"Carat", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeySpace}, "^"},
{"Carat-a", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyA}, "â"},
{"Carat-e", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyE}, "ê"},
{"Carat-i", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyI}, "î"},
{"Carat-o", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyO}, "ô"},
{"Carat-u", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyU}, "û"},
{"Carat-A", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyLShift, vt.KeyA}, "Â"},
{"Carat-E", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyLShift, vt.KeyE}, "Ê"},
{"Carat-I", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyLShift, vt.KeyI}, "Î"},
{"Carat-O", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyLShift, vt.KeyO}, "Ô"},
{"Carat-U", []vt.Key{vt.KeyLShift, vt.Key6}, []vt.Key{vt.KeyLShift, vt.KeyU}, "Û"},
{"Acute", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeySpace}, "'"},
{"Acute-a", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyA}, "á"},
{"Acute-c", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyC}, "ç"},
{"Acute-e", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyE}, "é"},
{"Acute-i", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyI}, "í"},
{"Acute-o", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyO}, "ó"},
{"Acute-u", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyU}, "ú"},
{"Acute-y", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyY}, "ý"},
{"Acute-A", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyA}, "Á"},
{"Acute-C", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyC}, "Ç"},
{"Acute-E", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyE}, "É"},
{"Acute-I", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyI}, "Í"},
{"Acute-O", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyO}, "Ó"},
{"Acute-U", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyU}, "Ú"},
{"Acute-Y", []vt.Key{vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyY}, "Ý"},
{"Quotes", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeySpace}, "\""},
{"Quotes-a", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyA}, "ä"},
{"Quotes-e", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyE}, "ë"},
{"Quotes-i", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyI}, "ï"},
{"Quotes-o", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyO}, "ö"},
{"Quotes-u", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyU}, "ü"},
{"Quotes-y", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyY}, "ÿ"},
{"Quotes-A", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyA}, "Ä"},
{"Quotes-E", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyE}, "Ë"},
{"Quotes-I", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyI}, "Ï"},
{"Quotes-O", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyO}, "Ö"},
{"Quotes-U", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyU}, "Ü"},
{"Quotes-Y", []vt.Key{vt.KeyLShift, vt.KeyQuote}, []vt.Key{vt.KeyLShift, vt.KeyY}, "Ÿ"},
{"Grave", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeySpace}, "`"},
{"Grave-a", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyA}, "à"},
{"Grave-e", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyE}, "è"},
{"Grave-i", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyI}, "ì"},
{"Grave-o", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyO}, "ò"},
{"Grave-u", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyU}, "ù"},
{"Grave-A", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyA}, "À"},
{"Grave-E", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyE}, "È"},
{"Grave-I", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyI}, "Ì"},
{"Grave-O", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyO}, "Ò"},
{"Grave-U", []vt.Key{vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyU}, "Ù"},
{"Tilde-a", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyA}, "ã"},
{"Tilde-n", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyN}, "ñ"},
{"Tilde-o", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyO}, "õ"},
{"Tilde-A", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyA}, "Ã"},
{"Tilde-N", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyN}, "Ñ"},
{"Tilde-O", []vt.Key{vt.KeyLShift, vt.KeyGrave}, []vt.Key{vt.KeyLShift, vt.KeyO}, "Õ"},
}
for i := range cases {
t.Run(cases[i].name, func(t *testing.T) {
term.KeyTap(cases[i].keys...)
term.KeyTap(cases[i].key...)
term.KeyTap(vt.KeySpace) // add a vanilla space to force output if empty
CheckRead(t, term, cases[i].want+" ")
})
}
}
func TestUsCapsLock(t *testing.T) {
term := vt.NewMockTerm(vt.MockOptSize{X: 8, Y: 4})
defer MustClose(t, term)
term.SetLayout(vt.GetLayout("US International"))
MustStart(t, term)
cases := []struct {
name string
keys []vt.Key
caps string
base string
}{
{"A", []vt.Key{vt.KeyA}, "A", "a"},
{"B", []vt.Key{vt.KeyB}, "B", "b"},
{"1", []vt.Key{vt.Key1}, "1", "!"},
{"Z", []vt.Key{vt.KeyZ}, "Z", "z"},
{"plus", []vt.Key{vt.KeyEqual}, "=", "+"},
}
for i := range cases {
t.Run(cases[i].name, func(t *testing.T) {
// set caps lock
term.KeyTap(vt.KeyCapsLock)
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].caps+" ")
term.KeyTap(append([]vt.Key{vt.KeyLShift}, cases[i].keys...)...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].base+" ")
// release caps lock
term.KeyTap(vt.KeyCapsLock)
})
}
}
func TestUsNumLock(t *testing.T) {
term := vt.NewMockTerm(vt.MockOptSize{X: 8, Y: 4})
defer MustClose(t, term)
term.SetLayout(vt.GetLayout("US International"))
MustStart(t, term)
cases := []struct {
name string
keys []vt.Key
lock string
app string
num string
}{
{"1", []vt.Key{vt.KeyPad1}, "1", "\x1bOF", "1"},
{"2", []vt.Key{vt.KeyPad2}, "2", "\x1b[B", "2"},
{"3", []vt.Key{vt.KeyPad3}, "3", "\x1b[6~", "3"},
{"4", []vt.Key{vt.KeyPad4}, "4", "\x1b[D", "4"},
{"5", []vt.Key{vt.KeyPad5}, "5", "\x1b[E", "5"},
{"6", []vt.Key{vt.KeyPad6}, "6", "\x1b[C", "6"},
{"7", []vt.Key{vt.KeyPad7}, "7", "\x1bOH", "7"},
{"8", []vt.Key{vt.KeyPad8}, "8", "\x1b[A", "8"},
{"9", []vt.Key{vt.KeyPad9}, "9", "\x1b[5~", "9"},
{"0", []vt.Key{vt.KeyPad0}, "0", "\x1b[2~", "0"},
{"dec", []vt.Key{vt.KeyPadDec}, ".", "\x1b[3~", "."},
{"add", []vt.Key{vt.KeyPadAdd}, "+", "\x1bOk", "+"},
{"sub", []vt.Key{vt.KeyPadSub}, "-", "\x1bOm", "-"},
{"mul", []vt.Key{vt.KeyPadMul}, "*", "\x1bOj", "*"},
{"div", []vt.Key{vt.KeyPadDiv}, "/", "\x1bOo", "/"},
{"equal", []vt.Key{vt.KeyPadEqual}, "=", "\x1bOX", "="},
{"enter", []vt.Key{vt.KeyPadEnter}, "\r", "\x1bOM", "\r"},
}
for i := range cases {
t.Run(cases[i].name, func(t *testing.T) {
// set num lock
term.KeyTap(vt.KeyNumLock)
// set application mode
WriteF(t, term, "\x1b=")
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].lock+" ")
// clear application mode - should not change (NumLock takes precedence)
WriteF(t, term, "\x1b>")
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].lock+" ")
// release num lock
term.KeyTap(vt.KeyNumLock)
// set application mode
WriteF(t, term, "\x1b=")
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].app+" ")
WriteF(t, term, "\x1b>")
term.KeyTap(cases[i].keys...)
term.KeyTap(vt.KeySpace)
CheckRead(t, term, cases[i].num+" ")
})
}
}