From eb2eee4d987964dbfd3fd6df07e962aeef0567fd Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 15 Aug 2024 13:52:03 -0400 Subject: [PATCH] refactor: rename KeySym to KeyType and make KeyRunes the default --- key.go | 57 ++++--- key_deprecated.go | 16 -- key_test.go | 88 +++++------ kitty.go | 9 +- parse.go | 107 ++++++------- parse_test.go | 14 +- table.go | 320 ++++++++++++++++++------------------- terminfo.go | 396 +++++++++++++++++++++++----------------------- tty.go | 24 +-- win32input.go | 146 ++++++++--------- xterm.go | 10 +- 11 files changed, 585 insertions(+), 602 deletions(-) diff --git a/key.go b/key.go index 2d478681d1..9997321037 100644 --- a/key.go +++ b/key.go @@ -1,18 +1,26 @@ package tea -// KeySym is a keyboard symbol. -type KeySym int +// KeyType indicates whether the key is a special key or runes. Special +// keys are things like KeyEnter, KeyBackspace, and so on. Runes keys are just +// regular characters like 'a', '你', 'ض', '🦄', and so on. +// +// k := Key{Type: KeyRunes, Runes: []rune{'A'}, Mod: ModShift} +// if k.Type == KeyRunes { +// +// fmt.Println(k.Runes) +// // Output: A +// +// fmt.Println(k.String()) +// // Output: shift+a +// +// } +type KeyType int // Special key symbols. const ( // KeyRunes indicates that the key represents rune(s), like 'a', 'b', 'c', // and so on. - KeyRunes KeySym = iota - 1 - - // KeyNone indicates that this key is not a special key. Combined with - // `len(k.Runes) > 0`, this indicates that the key represents rune(s) with - // modifiers like [ModCtrl], [ModAlt], [ModShift], and so on. - KeyNone + KeyRunes KeyType = iota // Special names in C0 @@ -218,8 +226,8 @@ const ( // one character, though certain input method editors (most notably Chinese // IMEs) can input multiple runes at once. type Key struct { - // Sym is a special key, like enter, tab, backspace, and so on. - Sym KeySym + // Type is a special key, like enter, tab, backspace, and so on. + Type KeyType // Runes contains the actual characters received. This usually has a length // of 1. Use [Rune()] to get the first key rune received. If the user @@ -315,22 +323,22 @@ func (k Key) Rune() rune { // "shift+ctrl+alt+a". func (k Key) String() string { var s string - if k.Mod.HasCtrl() && k.Sym != KeyLeftCtrl && k.Sym != KeyRightCtrl { + if k.Mod.HasCtrl() && k.Type != KeyLeftCtrl && k.Type != KeyRightCtrl { s += "ctrl+" } - if k.Mod.HasAlt() && k.Sym != KeyLeftAlt && k.Sym != KeyRightAlt { + if k.Mod.HasAlt() && k.Type != KeyLeftAlt && k.Type != KeyRightAlt { s += "alt+" } - if k.Mod.HasShift() && k.Sym != KeyLeftShift && k.Sym != KeyRightShift { + if k.Mod.HasShift() && k.Type != KeyLeftShift && k.Type != KeyRightShift { s += "shift+" } - if k.Mod.HasMeta() && k.Sym != KeyLeftMeta && k.Sym != KeyRightMeta { + if k.Mod.HasMeta() && k.Type != KeyLeftMeta && k.Type != KeyRightMeta { s += "meta+" } - if k.Mod.HasHyper() && k.Sym != KeyLeftHyper && k.Sym != KeyRightHyper { + if k.Mod.HasHyper() && k.Type != KeyLeftHyper && k.Type != KeyRightHyper { s += "hyper+" } - if k.Mod.HasSuper() && k.Sym != KeyLeftSuper && k.Sym != KeyRightSuper { + if k.Mod.HasSuper() && k.Type != KeyLeftSuper && k.Type != KeyRightSuper { s += "super+" } @@ -356,22 +364,21 @@ func (k Key) String() string { s += runeStr(k.Rune()) } } else { - s += k.Sym.String() + s += k.Type.String() } return s } -// String implements fmt.Stringer and prints the string representation of a of -// a Symbol key. -func (k KeySym) String() string { - s, ok := keySymString[k] - if !ok { - return "unknown" +// String returns the string representation of the key type. +func (k KeyType) String() string { + if s, ok := keyTypeString[k]; ok { + return s } - return s + return "" } -var keySymString = map[KeySym]string{ +var keyTypeString = map[KeyType]string{ + KeyRunes: "runes", KeyEnter: "enter", KeyTab: "tab", KeyBackspace: "backspace", diff --git a/key_deprecated.go b/key_deprecated.go index f40c2a4905..ab1c9de1a8 100644 --- a/key_deprecated.go +++ b/key_deprecated.go @@ -79,22 +79,6 @@ func (k KeyMsg) String() (str string) { return "" } -// KeyType indicates the key pressed, such as KeyEnter or KeyBreak or KeyCtrlC. -// All other keys will be type KeyRunes. To get the rune value, check the Rune -// method on a Key struct, or use the Key.String() method: -// -// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} -// if k.Type == KeyRunes { -// -// fmt.Println(k.Runes) -// // Output: a -// -// fmt.Println(k.String()) -// // Output: alt+a -// -// } -type KeyType = KeySym - // Control key aliases. const ( KeyNull KeyType = -iota - 10 diff --git a/key_test.go b/key_test.go index ed04dafe5c..d46da05379 100644 --- a/key_test.go +++ b/key_test.go @@ -24,7 +24,7 @@ var sequences = buildKeysTable(_FlagTerminfo, "dumb") func TestKeyString(t *testing.T) { t.Run("alt+space", func(t *testing.T) { - k := KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}, Mod: ModAlt} + k := KeyPressMsg{Type: KeySpace, Runes: []rune{' '}, Mod: ModAlt} if got := k.String(); got != "alt+space" { t.Fatalf(`expected a "alt+space ", got %q`, got) } @@ -38,8 +38,8 @@ func TestKeyString(t *testing.T) { }) t.Run("invalid", func(t *testing.T) { - k := KeyPressMsg{Sym: 99999} - if got := k.String(); got != "unknown" { + k := KeyPressMsg{Type: 99999} + if got := k.String(); got != "" { t.Fatalf(`expected a "unknown", got %q`, got) } }) @@ -53,7 +53,7 @@ func TestKeyTypeString(t *testing.T) { }) t.Run("invalid", func(t *testing.T) { - if got := KeySym(99999).String(); got != "unknown" { + if got := KeyType(99999).String(); got != "" { t.Fatalf(`expected a "unknown", got %q`, got) } }) @@ -96,14 +96,14 @@ func buildBaseSeqTests() []seqTest { seqTest{ []byte{' '}, []Msg{ - KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}}, + KeyPressMsg{Type: KeySpace, Runes: []rune{' '}}, }, }, // An escape character with the alt modifier. seqTest{ []byte{'\x1b', ' '}, []Msg{ - KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}, Mod: ModAlt}, + KeyPressMsg{Type: KeySpace, Runes: []rune{' '}, Mod: ModAlt}, }, }, ) @@ -144,7 +144,7 @@ func TestParseSequence(t *testing.T) { seqTest{ []byte{'a'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, }, }, seqTest{ @@ -156,16 +156,16 @@ func TestParseSequence(t *testing.T) { seqTest{ []byte{'a', 'a', 'a'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, }, }, // Multi-byte rune. seqTest{ []byte("☃"), []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'☃'}}, + KeyPressMsg{Runes: []rune{'☃'}}, }, }, seqTest{ @@ -178,7 +178,7 @@ func TestParseSequence(t *testing.T) { seqTest{ []byte{'\x1b'}, []Msg{ - KeyPressMsg{Sym: KeyEscape}, + KeyPressMsg{Type: KeyEscape}, }, }, seqTest{ @@ -196,13 +196,13 @@ func TestParseSequence(t *testing.T) { seqTest{ []byte{ansi.NUL}, []Msg{ - KeyPressMsg{Runes: []rune{' '}, Sym: KeySpace, Mod: ModCtrl}, + KeyPressMsg{Runes: []rune{' '}, Type: KeySpace, Mod: ModCtrl}, }, }, seqTest{ []byte{'\x1b', ansi.NUL}, []Msg{ - KeyPressMsg{Runes: []rune{' '}, Sym: KeySpace, Mod: ModCtrl | ModAlt}, + KeyPressMsg{Runes: []rune{' '}, Type: KeySpace, Mod: ModCtrl | ModAlt}, }, }, // C1 control characters. @@ -249,7 +249,7 @@ func TestParseSequence(t *testing.T) { func TestReadLongInput(t *testing.T) { expect := make([]Msg, 1000) for i := 0; i < 1000; i++ { - expect[i] = KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}} + expect[i] = KeyPressMsg{Runes: []rune{'a'}} } input := strings.Repeat("a", 1000) drv, err := newDriver(strings.NewReader(input), "dumb", 0) @@ -285,21 +285,21 @@ func TestReadInput(t *testing.T) { "a", []byte{'a'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, }, }, { "space", []byte{' '}, []Msg{ - KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}}, + KeyPressMsg{Type: KeySpace, Runes: []rune{' '}}, }, }, { "a alt+a", []byte{'a', '\x1b', 'a'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, KeyPressMsg{Runes: []rune{'a'}, Mod: ModAlt}, }, }, @@ -307,9 +307,9 @@ func TestReadInput(t *testing.T) { "a alt+a a", []byte{'a', '\x1b', 'a', 'a'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, KeyPressMsg{Runes: []rune{'a'}, Mod: ModAlt}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, }, }, { @@ -331,24 +331,24 @@ func TestReadInput(t *testing.T) { "alt+a", []byte{byte(0x1b), 'a'}, []Msg{ - KeyPressMsg{Sym: KeyNone, Mod: ModAlt, Runes: []rune{'a'}}, + KeyPressMsg{Mod: ModAlt, Runes: []rune{'a'}}, }, }, { "a b c d", []byte{'a', 'b', 'c', 'd'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'b'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'c'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'d'}}, + KeyPressMsg{Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'b'}}, + KeyPressMsg{Runes: []rune{'c'}}, + KeyPressMsg{Runes: []rune{'d'}}, }, }, { "up", []byte("\x1b[A"), []Msg{ - KeyPressMsg{Sym: KeyUp}, + KeyPressMsg{Type: KeyUp}, }, }, { @@ -373,26 +373,26 @@ func TestReadInput(t *testing.T) { "shift+tab", []byte{'\x1b', '[', 'Z'}, []Msg{ - KeyPressMsg{Sym: KeyTab, Mod: ModShift}, + KeyPressMsg{Type: KeyTab, Mod: ModShift}, }, }, { "enter", []byte{'\r'}, - []Msg{KeyPressMsg{Sym: KeyEnter}}, + []Msg{KeyPressMsg{Type: KeyEnter}}, }, { "alt+enter", []byte{'\x1b', '\r'}, []Msg{ - KeyPressMsg{Sym: KeyEnter, Mod: ModAlt}, + KeyPressMsg{Type: KeyEnter, Mod: ModAlt}, }, }, { "insert", []byte{'\x1b', '[', '2', '~'}, []Msg{ - KeyPressMsg{Sym: KeyInsert}, + KeyPressMsg{Type: KeyInsert}, }, }, { @@ -411,52 +411,52 @@ func TestReadInput(t *testing.T) { { "up", []byte{'\x1b', 'O', 'A'}, - []Msg{KeyPressMsg{Sym: KeyUp}}, + []Msg{KeyPressMsg{Type: KeyUp}}, }, { "down", []byte{'\x1b', 'O', 'B'}, - []Msg{KeyPressMsg{Sym: KeyDown}}, + []Msg{KeyPressMsg{Type: KeyDown}}, }, { "right", []byte{'\x1b', 'O', 'C'}, - []Msg{KeyPressMsg{Sym: KeyRight}}, + []Msg{KeyPressMsg{Type: KeyRight}}, }, { "left", []byte{'\x1b', 'O', 'D'}, - []Msg{KeyPressMsg{Sym: KeyLeft}}, + []Msg{KeyPressMsg{Type: KeyLeft}}, }, { "alt+enter", []byte{'\x1b', '\x0d'}, - []Msg{KeyPressMsg{Sym: KeyEnter, Mod: ModAlt}}, + []Msg{KeyPressMsg{Type: KeyEnter, Mod: ModAlt}}, }, { "alt+backspace", []byte{'\x1b', '\x7f'}, - []Msg{KeyPressMsg{Sym: KeyBackspace, Mod: ModAlt}}, + []Msg{KeyPressMsg{Type: KeyBackspace, Mod: ModAlt}}, }, { "ctrl+space", []byte{'\x00'}, - []Msg{KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}, Mod: ModCtrl}}, + []Msg{KeyPressMsg{Type: KeySpace, Runes: []rune{' '}, Mod: ModCtrl}}, }, { "ctrl+alt+space", []byte{'\x1b', '\x00'}, - []Msg{KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}, Mod: ModCtrl | ModAlt}}, + []Msg{KeyPressMsg{Type: KeySpace, Runes: []rune{' '}, Mod: ModCtrl | ModAlt}}, }, { "esc", []byte{'\x1b'}, - []Msg{KeyPressMsg{Sym: KeyEscape}}, + []Msg{KeyPressMsg{Type: KeyEscape}}, }, { "alt+esc", []byte{'\x1b', '\x1b'}, - []Msg{KeyPressMsg{Sym: KeyEscape, Mod: ModAlt}}, + []Msg{KeyPressMsg{Type: KeyEscape, Mod: ModAlt}}, }, { "a b o", @@ -470,7 +470,7 @@ func TestReadInput(t *testing.T) { PasteStartMsg{}, PasteMsg("a b"), PasteEndMsg{}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'o'}}, + KeyPressMsg{Runes: []rune{'o'}}, }, }, { @@ -497,10 +497,10 @@ func TestReadInput(t *testing.T) { "a ?0xfe? b", []byte{'a', '\xfe', ' ', 'b'}, []Msg{ - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'a'}}, + KeyPressMsg{Runes: []rune{'a'}}, UnknownMsg(rune(0xfe)), - KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'b'}}, + KeyPressMsg{Type: KeySpace, Runes: []rune{' '}}, + KeyPressMsg{Runes: []rune{'b'}}, }, }, } diff --git a/kitty.go b/kitty.go index aae61d2427..ff6279d78d 100644 --- a/kitty.go +++ b/kitty.go @@ -36,7 +36,7 @@ func (e KittyKeyboardMsg) IsReportAssociatedKeys() bool { } // Kitty Clipboard Control Sequences -var kittyKeyMap = map[int]KeySym{ +var kittyKeyMap = map[int]KeyType{ ansi.BS: KeyBackspace, ansi.HT: KeyTab, ansi.CR: KeyEnter, @@ -216,14 +216,14 @@ func parseKittyKeyboard(csi *ansi.CsiSequence) Msg { if params := csi.Subparams(0); len(params) > 0 { code := params[0] if sym, ok := kittyKeyMap[code]; ok { - key.Sym = sym + key.Type = sym } else { r := rune(code) if !utf8.ValidRune(r) { r = utf8.RuneError } - key.Sym = KeyRunes + key.Type = KeyRunes key.Runes = []rune{r} // alternate key reporting @@ -258,9 +258,6 @@ func parseKittyKeyboard(csi *ansi.CsiSequence) Msg { mod := params[0] if mod > 1 { key.Mod = fromKittyMod(mod - 1) - if key.Sym == KeyRunes { - key.Sym = KeyNone - } } if len(params) > 1 { switch params[1] { diff --git a/parse.go b/parse.go index a140f09c16..49eae924fa 100644 --- a/parse.go +++ b/parse.go @@ -109,7 +109,7 @@ func parseSequence(buf []byte) (n int, msg Msg) { case ansi.ESC: if len(buf) == 1 { // Escape key - return 1, KeyPressMsg{Sym: KeyEscape} + return 1, KeyPressMsg{Type: KeyEscape} } switch b := buf[1]; b { @@ -127,15 +127,12 @@ func parseSequence(buf []byte) (n int, msg Msg) { n, e := parseSequence(buf[1:]) if k, ok := e.(KeyPressMsg); ok { k.Mod |= ModAlt - if k.Sym == KeyRunes { - k.Sym = KeyNone - } return n + 1, k } // Not a key sequence, nor an alt modified key sequence. In that // case, just report a single escape key. - return 1, KeyPressMsg{Sym: KeyEscape} + return 1, KeyPressMsg{Type: KeyEscape} } case ansi.SS3: return parseSs3(buf) @@ -242,7 +239,7 @@ func parseCsi(b []byte) (int, Msg) { switch cmd := csi.Cmd; cmd { case 'y' | '?'<= 2 { + if paramsLen >= 2 && csi.Param(0) != -1 && csi.Param(1) != -1 { return i, CursorPositionMsg{Row: csi.Param(0), Column: csi.Param(1)} } case 'm' | '<'<'< 1 && csi.Param(0) == 1 { + if paramsLen > 1 && csi.Param(0) == 1 && csi.Param(1) != -1 { // CSI 1 ; A - if paramsLen > 1 { - k.Mod |= KeyMod(csi.Param(1) - 1) - } + k.Mod |= KeyMod(csi.Param(1) - 1) } return i, k case 'M': @@ -329,7 +324,7 @@ func parseCsi(b []byte) (int, Msg) { return i + 3, parseX10MouseEvent(append(b[:i], b[i:i+3]...)) case 'y': // Report Mode (DECRPM) - if paramsLen != 2 { + if paramsLen != 2 && csi.Param(0) != -1 && csi.Param(0) != -1 { return i, UnknownMsg(b[:i]) } return i, ReportModeMsg{Mode: csi.Param(0), Value: csi.Param(1)} @@ -398,42 +393,42 @@ func parseCsi(b []byte) (int, Msg) { switch param { case 1: if flags&_FlagFind != 0 { - k = KeyPressMsg{Sym: KeyFind} + k = KeyPressMsg{Type: KeyFind} } else { - k = KeyPressMsg{Sym: KeyHome} + k = KeyPressMsg{Type: KeyHome} } case 2: - k = KeyPressMsg{Sym: KeyInsert} + k = KeyPressMsg{Type: KeyInsert} case 3: - k = KeyPressMsg{Sym: KeyDelete} + k = KeyPressMsg{Type: KeyDelete} case 4: if flags&_FlagSelect != 0 { - k = KeyPressMsg{Sym: KeySelect} + k = KeyPressMsg{Type: KeySelect} } else { - k = KeyPressMsg{Sym: KeyEnd} + k = KeyPressMsg{Type: KeyEnd} } case 5: - k = KeyPressMsg{Sym: KeyPgUp} + k = KeyPressMsg{Type: KeyPgUp} case 6: - k = KeyPressMsg{Sym: KeyPgDown} + k = KeyPressMsg{Type: KeyPgDown} case 7: - k = KeyPressMsg{Sym: KeyHome} + k = KeyPressMsg{Type: KeyHome} case 8: - k = KeyPressMsg{Sym: KeyEnd} + k = KeyPressMsg{Type: KeyEnd} case 11, 12, 13, 14, 15: - k = KeyPressMsg{Sym: KeyF1 + KeySym(param-11)} + k = KeyPressMsg{Type: KeyF1 + KeyType(param-11)} case 17, 18, 19, 20, 21: - k = KeyPressMsg{Sym: KeyF6 + KeySym(param-17)} + k = KeyPressMsg{Type: KeyF6 + KeyType(param-17)} case 23, 24, 25, 26: - k = KeyPressMsg{Sym: KeyF11 + KeySym(param-23)} + k = KeyPressMsg{Type: KeyF11 + KeyType(param-23)} case 28, 29: - k = KeyPressMsg{Sym: KeyF15 + KeySym(param-28)} + k = KeyPressMsg{Type: KeyF15 + KeyType(param-28)} case 31, 32, 33, 34: - k = KeyPressMsg{Sym: KeyF17 + KeySym(param-31)} + k = KeyPressMsg{Type: KeyF17 + KeyType(param-31)} } // modifiers - if paramsLen > 1 { + if paramsLen > 1 && csi.Param(1) != -1 { k.Mod |= KeyMod(csi.Param(1) - 1) } @@ -488,23 +483,23 @@ func parseSs3(b []byte) (int, Msg) { var k KeyPressMsg switch gl { case 'a', 'b', 'c', 'd': - k = KeyPressMsg{Sym: KeyUp + KeySym(gl-'a'), Mod: ModCtrl} + k = KeyPressMsg{Type: KeyUp + KeyType(gl-'a'), Mod: ModCtrl} case 'A', 'B', 'C', 'D': - k = KeyPressMsg{Sym: KeyUp + KeySym(gl-'A')} + k = KeyPressMsg{Type: KeyUp + KeyType(gl-'A')} case 'E': - k = KeyPressMsg{Sym: KeyBegin} + k = KeyPressMsg{Type: KeyBegin} case 'F': - k = KeyPressMsg{Sym: KeyEnd} + k = KeyPressMsg{Type: KeyEnd} case 'H': - k = KeyPressMsg{Sym: KeyHome} + k = KeyPressMsg{Type: KeyHome} case 'P', 'Q', 'R', 'S': - k = KeyPressMsg{Sym: KeyF1 + KeySym(gl-'P')} + k = KeyPressMsg{Type: KeyF1 + KeyType(gl-'P')} case 'M': - k = KeyPressMsg{Sym: KeyKpEnter} + k = KeyPressMsg{Type: KeyKpEnter} case 'X': - k = KeyPressMsg{Sym: KeyKpEqual} + k = KeyPressMsg{Type: KeyKpEqual} case 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y': - k = KeyPressMsg{Sym: KeyKpMultiply + KeySym(gl-'j')} + k = KeyPressMsg{Type: KeyKpMultiply + KeyType(gl-'j')} default: return i, UnknownMsg(b[:i]) } @@ -762,7 +757,7 @@ func parseUtf8(b []byte) (int, Msg) { return 1, parseControl(c) } else if c > ansi.US && c < ansi.DEL { // ASCII printable characters - return 1, KeyPressMsg{Sym: KeyRunes, Runes: []rune{rune(c)}} + return 1, KeyPressMsg{Runes: []rune{rune(c)}} } if r, _ := utf8.DecodeRune(b); r == utf8.RuneError { @@ -770,7 +765,7 @@ func parseUtf8(b []byte) (int, Msg) { } cluster, _, _, _ := uniseg.FirstGraphemeCluster(b, -1) - return len(cluster), KeyPressMsg{Sym: KeyRunes, Runes: []rune(string(cluster))} + return len(cluster), KeyPressMsg{Runes: []rune(string(cluster))} } func parseControl(b byte) Msg { @@ -779,31 +774,31 @@ func parseControl(b byte) Msg { if flags&_FlagCtrlAt != 0 { return KeyPressMsg{Runes: []rune{'@'}, Mod: ModCtrl} } - return KeyPressMsg{Runes: []rune{' '}, Sym: KeySpace, Mod: ModCtrl} + return KeyPressMsg{Runes: []rune{' '}, Type: KeySpace, Mod: ModCtrl} case ansi.BS: return KeyPressMsg{Runes: []rune{'h'}, Mod: ModCtrl} case ansi.HT: if flags&_FlagCtrlI != 0 { return KeyPressMsg{Runes: []rune{'i'}, Mod: ModCtrl} } - return KeyPressMsg{Sym: KeyTab} + return KeyPressMsg{Type: KeyTab} case ansi.CR: if flags&_FlagCtrlM != 0 { return KeyPressMsg{Runes: []rune{'m'}, Mod: ModCtrl} } - return KeyPressMsg{Sym: KeyEnter} + return KeyPressMsg{Type: KeyEnter} case ansi.ESC: if flags&_FlagCtrlOpenBracket != 0 { return KeyPressMsg{Runes: []rune{'['}, Mod: ModCtrl} } - return KeyPressMsg{Sym: KeyEscape} + return KeyPressMsg{Type: KeyEscape} case ansi.DEL: if flags&_FlagBackspace != 0 { - return KeyPressMsg{Sym: KeyDelete} + return KeyPressMsg{Type: KeyDelete} } - return KeyPressMsg{Sym: KeyBackspace} + return KeyPressMsg{Type: KeyBackspace} case ansi.SP: - return KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}} + return KeyPressMsg{Type: KeySpace, Runes: []rune{' '}} default: if b >= ansi.SOH && b <= ansi.SUB { // Use lower case letters for control codes diff --git a/parse_test.go b/parse_test.go index 1f3ccfc6d5..6e8e0b6170 100644 --- a/parse_test.go +++ b/parse_test.go @@ -9,14 +9,14 @@ import ( func TestParseSequence_Events(t *testing.T) { input := []byte("\x1b\x1b[Ztest\x00\x1b]10;rgb:1234/1234/1234\x07\x1b[27;2;27~\x1b[?1049;2$y") want := []Msg{ - KeyPressMsg{Sym: KeyTab, Mod: ModShift | ModAlt}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'t'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'e'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'s'}}, - KeyPressMsg{Sym: KeyRunes, Runes: []rune{'t'}}, - KeyPressMsg{Sym: KeySpace, Runes: []rune{' '}, Mod: ModCtrl}, + KeyPressMsg{Type: KeyTab, Mod: ModShift | ModAlt}, + KeyPressMsg{Type: KeyRunes, Runes: []rune{'t'}}, + KeyPressMsg{Type: KeyRunes, Runes: []rune{'e'}}, + KeyPressMsg{Type: KeyRunes, Runes: []rune{'s'}}, + KeyPressMsg{Type: KeyRunes, Runes: []rune{'t'}}, + KeyPressMsg{Type: KeySpace, Runes: []rune{' '}, Mod: ModCtrl}, ForegroundColorMsg{color.RGBA{R: 0x12, G: 0x12, B: 0x12, A: 0xff}}, - KeyPressMsg{Sym: KeyEscape, Mod: ModShift}, + KeyPressMsg{Type: KeyEscape, Mod: ModShift}, ReportModeMsg{Mode: 1049, Value: 2}, } for i := 0; len(input) != 0; i++ { diff --git a/table.go b/table.go index 4b350643b2..678388cdd9 100644 --- a/table.go +++ b/table.go @@ -10,39 +10,39 @@ import ( // events based on the VT100/VT200, XTerm, and Urxvt terminal specs. // TODO: Use flags? func buildKeysTable(flags int, term string) map[string]Key { - nul := Key{Runes: []rune{' '}, Sym: KeySpace, Mod: ModCtrl} // ctrl+@ or ctrl+space + nul := Key{Runes: []rune{' '}, Type: KeySpace, Mod: ModCtrl} // ctrl+@ or ctrl+space if flags&_FlagCtrlAt != 0 { nul = Key{Runes: []rune{'@'}, Mod: ModCtrl} } - tab := Key{Sym: KeyTab} // ctrl+i or tab + tab := Key{Type: KeyTab} // ctrl+i or tab if flags&_FlagCtrlI != 0 { tab = Key{Runes: []rune{'i'}, Mod: ModCtrl} } - enter := Key{Sym: KeyEnter} // ctrl+m or enter + enter := Key{Type: KeyEnter} // ctrl+m or enter if flags&_FlagCtrlM != 0 { enter = Key{Runes: []rune{'m'}, Mod: ModCtrl} } - esc := Key{Sym: KeyEscape} // ctrl+[ or escape + esc := Key{Type: KeyEscape} // ctrl+[ or escape if flags&_FlagCtrlOpenBracket != 0 { esc = Key{Runes: []rune{'['}, Mod: ModCtrl} // ctrl+[ or escape } - del := Key{Sym: KeyBackspace} + del := Key{Type: KeyBackspace} if flags&_FlagBackspace != 0 { - del.Sym = KeyDelete + del.Type = KeyDelete } - find := Key{Sym: KeyHome} + find := Key{Type: KeyHome} if flags&_FlagFind != 0 { - find.Sym = KeyFind + find.Type = KeyFind } - sel := Key{Sym: KeyEnd} + sel := Key{Type: KeyEnd} if flags&_FlagSelect != 0 { - sel.Sym = KeySelect + sel.Type = KeySelect } // The following is a table of key sequences and their corresponding key @@ -89,122 +89,122 @@ func buildKeysTable(flags int, term string) map[string]Key { string(byte(ansi.US)): {Runes: []rune{'_'}, Mod: ModCtrl}, // Special keys in G0 - string(byte(ansi.SP)): {Sym: KeySpace, Runes: []rune{' '}}, + string(byte(ansi.SP)): {Type: KeySpace, Runes: []rune{' '}}, string(byte(ansi.DEL)): del, // Special keys - "\x1b[Z": {Sym: KeyTab, Mod: ModShift}, + "\x1b[Z": {Type: KeyTab, Mod: ModShift}, "\x1b[1~": find, - "\x1b[2~": {Sym: KeyInsert}, - "\x1b[3~": {Sym: KeyDelete}, + "\x1b[2~": {Type: KeyInsert}, + "\x1b[3~": {Type: KeyDelete}, "\x1b[4~": sel, - "\x1b[5~": {Sym: KeyPgUp}, - "\x1b[6~": {Sym: KeyPgDown}, - "\x1b[7~": {Sym: KeyHome}, - "\x1b[8~": {Sym: KeyEnd}, + "\x1b[5~": {Type: KeyPgUp}, + "\x1b[6~": {Type: KeyPgDown}, + "\x1b[7~": {Type: KeyHome}, + "\x1b[8~": {Type: KeyEnd}, // Normal mode - "\x1b[A": {Sym: KeyUp}, - "\x1b[B": {Sym: KeyDown}, - "\x1b[C": {Sym: KeyRight}, - "\x1b[D": {Sym: KeyLeft}, - "\x1b[E": {Sym: KeyBegin}, - "\x1b[F": {Sym: KeyEnd}, - "\x1b[H": {Sym: KeyHome}, - "\x1b[P": {Sym: KeyF1}, - "\x1b[Q": {Sym: KeyF2}, - "\x1b[R": {Sym: KeyF3}, - "\x1b[S": {Sym: KeyF4}, + "\x1b[A": {Type: KeyUp}, + "\x1b[B": {Type: KeyDown}, + "\x1b[C": {Type: KeyRight}, + "\x1b[D": {Type: KeyLeft}, + "\x1b[E": {Type: KeyBegin}, + "\x1b[F": {Type: KeyEnd}, + "\x1b[H": {Type: KeyHome}, + "\x1b[P": {Type: KeyF1}, + "\x1b[Q": {Type: KeyF2}, + "\x1b[R": {Type: KeyF3}, + "\x1b[S": {Type: KeyF4}, // Application Cursor Key Mode (DECCKM) - "\x1bOA": {Sym: KeyUp}, - "\x1bOB": {Sym: KeyDown}, - "\x1bOC": {Sym: KeyRight}, - "\x1bOD": {Sym: KeyLeft}, - "\x1bOE": {Sym: KeyBegin}, - "\x1bOF": {Sym: KeyEnd}, - "\x1bOH": {Sym: KeyHome}, - "\x1bOP": {Sym: KeyF1}, - "\x1bOQ": {Sym: KeyF2}, - "\x1bOR": {Sym: KeyF3}, - "\x1bOS": {Sym: KeyF4}, + "\x1bOA": {Type: KeyUp}, + "\x1bOB": {Type: KeyDown}, + "\x1bOC": {Type: KeyRight}, + "\x1bOD": {Type: KeyLeft}, + "\x1bOE": {Type: KeyBegin}, + "\x1bOF": {Type: KeyEnd}, + "\x1bOH": {Type: KeyHome}, + "\x1bOP": {Type: KeyF1}, + "\x1bOQ": {Type: KeyF2}, + "\x1bOR": {Type: KeyF3}, + "\x1bOS": {Type: KeyF4}, // Keypad Application Mode (DECKPAM) - "\x1bOM": {Sym: KeyKpEnter}, - "\x1bOX": {Sym: KeyKpEqual}, - "\x1bOj": {Sym: KeyKpMultiply}, - "\x1bOk": {Sym: KeyKpPlus}, - "\x1bOl": {Sym: KeyKpComma}, - "\x1bOm": {Sym: KeyKpMinus}, - "\x1bOn": {Sym: KeyKpDecimal}, - "\x1bOo": {Sym: KeyKpDivide}, - "\x1bOp": {Sym: KeyKp0}, - "\x1bOq": {Sym: KeyKp1}, - "\x1bOr": {Sym: KeyKp2}, - "\x1bOs": {Sym: KeyKp3}, - "\x1bOt": {Sym: KeyKp4}, - "\x1bOu": {Sym: KeyKp5}, - "\x1bOv": {Sym: KeyKp6}, - "\x1bOw": {Sym: KeyKp7}, - "\x1bOx": {Sym: KeyKp8}, - "\x1bOy": {Sym: KeyKp9}, + "\x1bOM": {Type: KeyKpEnter}, + "\x1bOX": {Type: KeyKpEqual}, + "\x1bOj": {Type: KeyKpMultiply}, + "\x1bOk": {Type: KeyKpPlus}, + "\x1bOl": {Type: KeyKpComma}, + "\x1bOm": {Type: KeyKpMinus}, + "\x1bOn": {Type: KeyKpDecimal}, + "\x1bOo": {Type: KeyKpDivide}, + "\x1bOp": {Type: KeyKp0}, + "\x1bOq": {Type: KeyKp1}, + "\x1bOr": {Type: KeyKp2}, + "\x1bOs": {Type: KeyKp3}, + "\x1bOt": {Type: KeyKp4}, + "\x1bOu": {Type: KeyKp5}, + "\x1bOv": {Type: KeyKp6}, + "\x1bOw": {Type: KeyKp7}, + "\x1bOx": {Type: KeyKp8}, + "\x1bOy": {Type: KeyKp9}, // Function keys - "\x1b[11~": {Sym: KeyF1}, - "\x1b[12~": {Sym: KeyF2}, - "\x1b[13~": {Sym: KeyF3}, - "\x1b[14~": {Sym: KeyF4}, - "\x1b[15~": {Sym: KeyF5}, - "\x1b[17~": {Sym: KeyF6}, - "\x1b[18~": {Sym: KeyF7}, - "\x1b[19~": {Sym: KeyF8}, - "\x1b[20~": {Sym: KeyF9}, - "\x1b[21~": {Sym: KeyF10}, - "\x1b[23~": {Sym: KeyF11}, - "\x1b[24~": {Sym: KeyF12}, - "\x1b[25~": {Sym: KeyF13}, - "\x1b[26~": {Sym: KeyF14}, - "\x1b[28~": {Sym: KeyF15}, - "\x1b[29~": {Sym: KeyF16}, - "\x1b[31~": {Sym: KeyF17}, - "\x1b[32~": {Sym: KeyF18}, - "\x1b[33~": {Sym: KeyF19}, - "\x1b[34~": {Sym: KeyF20}, + "\x1b[11~": {Type: KeyF1}, + "\x1b[12~": {Type: KeyF2}, + "\x1b[13~": {Type: KeyF3}, + "\x1b[14~": {Type: KeyF4}, + "\x1b[15~": {Type: KeyF5}, + "\x1b[17~": {Type: KeyF6}, + "\x1b[18~": {Type: KeyF7}, + "\x1b[19~": {Type: KeyF8}, + "\x1b[20~": {Type: KeyF9}, + "\x1b[21~": {Type: KeyF10}, + "\x1b[23~": {Type: KeyF11}, + "\x1b[24~": {Type: KeyF12}, + "\x1b[25~": {Type: KeyF13}, + "\x1b[26~": {Type: KeyF14}, + "\x1b[28~": {Type: KeyF15}, + "\x1b[29~": {Type: KeyF16}, + "\x1b[31~": {Type: KeyF17}, + "\x1b[32~": {Type: KeyF18}, + "\x1b[33~": {Type: KeyF19}, + "\x1b[34~": {Type: KeyF20}, } // CSI ~ sequence keys csiTildeKeys := map[string]Key{ - "1": find, "2": {Sym: KeyInsert}, - "3": {Sym: KeyDelete}, "4": sel, - "5": {Sym: KeyPgUp}, "6": {Sym: KeyPgDown}, - "7": {Sym: KeyHome}, "8": {Sym: KeyEnd}, + "1": find, "2": {Type: KeyInsert}, + "3": {Type: KeyDelete}, "4": sel, + "5": {Type: KeyPgUp}, "6": {Type: KeyPgDown}, + "7": {Type: KeyHome}, "8": {Type: KeyEnd}, // There are no 9 and 10 keys - "11": {Sym: KeyF1}, "12": {Sym: KeyF2}, - "13": {Sym: KeyF3}, "14": {Sym: KeyF4}, - "15": {Sym: KeyF5}, "17": {Sym: KeyF6}, - "18": {Sym: KeyF7}, "19": {Sym: KeyF8}, - "20": {Sym: KeyF9}, "21": {Sym: KeyF10}, - "23": {Sym: KeyF11}, "24": {Sym: KeyF12}, - "25": {Sym: KeyF13}, "26": {Sym: KeyF14}, - "28": {Sym: KeyF15}, "29": {Sym: KeyF16}, - "31": {Sym: KeyF17}, "32": {Sym: KeyF18}, - "33": {Sym: KeyF19}, "34": {Sym: KeyF20}, + "11": {Type: KeyF1}, "12": {Type: KeyF2}, + "13": {Type: KeyF3}, "14": {Type: KeyF4}, + "15": {Type: KeyF5}, "17": {Type: KeyF6}, + "18": {Type: KeyF7}, "19": {Type: KeyF8}, + "20": {Type: KeyF9}, "21": {Type: KeyF10}, + "23": {Type: KeyF11}, "24": {Type: KeyF12}, + "25": {Type: KeyF13}, "26": {Type: KeyF14}, + "28": {Type: KeyF15}, "29": {Type: KeyF16}, + "31": {Type: KeyF17}, "32": {Type: KeyF18}, + "33": {Type: KeyF19}, "34": {Type: KeyF20}, } // URxvt keys // See https://manpages.ubuntu.com/manpages/trusty/man7/urxvt.7.html#key%20codes - table["\x1b[a"] = Key{Sym: KeyUp, Mod: ModShift} - table["\x1b[b"] = Key{Sym: KeyDown, Mod: ModShift} - table["\x1b[c"] = Key{Sym: KeyRight, Mod: ModShift} - table["\x1b[d"] = Key{Sym: KeyLeft, Mod: ModShift} - table["\x1bOa"] = Key{Sym: KeyUp, Mod: ModCtrl} - table["\x1bOb"] = Key{Sym: KeyDown, Mod: ModCtrl} - table["\x1bOc"] = Key{Sym: KeyRight, Mod: ModCtrl} - table["\x1bOd"] = Key{Sym: KeyLeft, Mod: ModCtrl} + table["\x1b[a"] = Key{Type: KeyUp, Mod: ModShift} + table["\x1b[b"] = Key{Type: KeyDown, Mod: ModShift} + table["\x1b[c"] = Key{Type: KeyRight, Mod: ModShift} + table["\x1b[d"] = Key{Type: KeyLeft, Mod: ModShift} + table["\x1bOa"] = Key{Type: KeyUp, Mod: ModCtrl} + table["\x1bOb"] = Key{Type: KeyDown, Mod: ModCtrl} + table["\x1bOc"] = Key{Type: KeyRight, Mod: ModCtrl} + table["\x1bOd"] = Key{Type: KeyLeft, Mod: ModCtrl} // TODO: invistigate if shift-ctrl arrow keys collide with DECCKM keys i.e. // "\x1bOA", "\x1bOB", "\x1bOC", "\x1bOD" @@ -232,46 +232,46 @@ func buildKeysTable(flags int, term string) map[string]Key { // different escapes like XTerm, or switch to a better terminal ¯\_(ツ)_/¯ // // See https://manpages.ubuntu.com/manpages/trusty/man7/urxvt.7.html#key%20codes - table["\x1b[23$"] = Key{Sym: KeyF11, Mod: ModShift} - table["\x1b[24$"] = Key{Sym: KeyF12, Mod: ModShift} - table["\x1b[25$"] = Key{Sym: KeyF13, Mod: ModShift} - table["\x1b[26$"] = Key{Sym: KeyF14, Mod: ModShift} - table["\x1b[28$"] = Key{Sym: KeyF15, Mod: ModShift} - table["\x1b[29$"] = Key{Sym: KeyF16, Mod: ModShift} - table["\x1b[31$"] = Key{Sym: KeyF17, Mod: ModShift} - table["\x1b[32$"] = Key{Sym: KeyF18, Mod: ModShift} - table["\x1b[33$"] = Key{Sym: KeyF19, Mod: ModShift} - table["\x1b[34$"] = Key{Sym: KeyF20, Mod: ModShift} - table["\x1b[11^"] = Key{Sym: KeyF1, Mod: ModCtrl} - table["\x1b[12^"] = Key{Sym: KeyF2, Mod: ModCtrl} - table["\x1b[13^"] = Key{Sym: KeyF3, Mod: ModCtrl} - table["\x1b[14^"] = Key{Sym: KeyF4, Mod: ModCtrl} - table["\x1b[15^"] = Key{Sym: KeyF5, Mod: ModCtrl} - table["\x1b[17^"] = Key{Sym: KeyF6, Mod: ModCtrl} - table["\x1b[18^"] = Key{Sym: KeyF7, Mod: ModCtrl} - table["\x1b[19^"] = Key{Sym: KeyF8, Mod: ModCtrl} - table["\x1b[20^"] = Key{Sym: KeyF9, Mod: ModCtrl} - table["\x1b[21^"] = Key{Sym: KeyF10, Mod: ModCtrl} - table["\x1b[23^"] = Key{Sym: KeyF11, Mod: ModCtrl} - table["\x1b[24^"] = Key{Sym: KeyF12, Mod: ModCtrl} - table["\x1b[25^"] = Key{Sym: KeyF13, Mod: ModCtrl} - table["\x1b[26^"] = Key{Sym: KeyF14, Mod: ModCtrl} - table["\x1b[28^"] = Key{Sym: KeyF15, Mod: ModCtrl} - table["\x1b[29^"] = Key{Sym: KeyF16, Mod: ModCtrl} - table["\x1b[31^"] = Key{Sym: KeyF17, Mod: ModCtrl} - table["\x1b[32^"] = Key{Sym: KeyF18, Mod: ModCtrl} - table["\x1b[33^"] = Key{Sym: KeyF19, Mod: ModCtrl} - table["\x1b[34^"] = Key{Sym: KeyF20, Mod: ModCtrl} - table["\x1b[23@"] = Key{Sym: KeyF11, Mod: ModShift | ModCtrl} - table["\x1b[24@"] = Key{Sym: KeyF12, Mod: ModShift | ModCtrl} - table["\x1b[25@"] = Key{Sym: KeyF13, Mod: ModShift | ModCtrl} - table["\x1b[26@"] = Key{Sym: KeyF14, Mod: ModShift | ModCtrl} - table["\x1b[28@"] = Key{Sym: KeyF15, Mod: ModShift | ModCtrl} - table["\x1b[29@"] = Key{Sym: KeyF16, Mod: ModShift | ModCtrl} - table["\x1b[31@"] = Key{Sym: KeyF17, Mod: ModShift | ModCtrl} - table["\x1b[32@"] = Key{Sym: KeyF18, Mod: ModShift | ModCtrl} - table["\x1b[33@"] = Key{Sym: KeyF19, Mod: ModShift | ModCtrl} - table["\x1b[34@"] = Key{Sym: KeyF20, Mod: ModShift | ModCtrl} + table["\x1b[23$"] = Key{Type: KeyF11, Mod: ModShift} + table["\x1b[24$"] = Key{Type: KeyF12, Mod: ModShift} + table["\x1b[25$"] = Key{Type: KeyF13, Mod: ModShift} + table["\x1b[26$"] = Key{Type: KeyF14, Mod: ModShift} + table["\x1b[28$"] = Key{Type: KeyF15, Mod: ModShift} + table["\x1b[29$"] = Key{Type: KeyF16, Mod: ModShift} + table["\x1b[31$"] = Key{Type: KeyF17, Mod: ModShift} + table["\x1b[32$"] = Key{Type: KeyF18, Mod: ModShift} + table["\x1b[33$"] = Key{Type: KeyF19, Mod: ModShift} + table["\x1b[34$"] = Key{Type: KeyF20, Mod: ModShift} + table["\x1b[11^"] = Key{Type: KeyF1, Mod: ModCtrl} + table["\x1b[12^"] = Key{Type: KeyF2, Mod: ModCtrl} + table["\x1b[13^"] = Key{Type: KeyF3, Mod: ModCtrl} + table["\x1b[14^"] = Key{Type: KeyF4, Mod: ModCtrl} + table["\x1b[15^"] = Key{Type: KeyF5, Mod: ModCtrl} + table["\x1b[17^"] = Key{Type: KeyF6, Mod: ModCtrl} + table["\x1b[18^"] = Key{Type: KeyF7, Mod: ModCtrl} + table["\x1b[19^"] = Key{Type: KeyF8, Mod: ModCtrl} + table["\x1b[20^"] = Key{Type: KeyF9, Mod: ModCtrl} + table["\x1b[21^"] = Key{Type: KeyF10, Mod: ModCtrl} + table["\x1b[23^"] = Key{Type: KeyF11, Mod: ModCtrl} + table["\x1b[24^"] = Key{Type: KeyF12, Mod: ModCtrl} + table["\x1b[25^"] = Key{Type: KeyF13, Mod: ModCtrl} + table["\x1b[26^"] = Key{Type: KeyF14, Mod: ModCtrl} + table["\x1b[28^"] = Key{Type: KeyF15, Mod: ModCtrl} + table["\x1b[29^"] = Key{Type: KeyF16, Mod: ModCtrl} + table["\x1b[31^"] = Key{Type: KeyF17, Mod: ModCtrl} + table["\x1b[32^"] = Key{Type: KeyF18, Mod: ModCtrl} + table["\x1b[33^"] = Key{Type: KeyF19, Mod: ModCtrl} + table["\x1b[34^"] = Key{Type: KeyF20, Mod: ModCtrl} + table["\x1b[23@"] = Key{Type: KeyF11, Mod: ModShift | ModCtrl} + table["\x1b[24@"] = Key{Type: KeyF12, Mod: ModShift | ModCtrl} + table["\x1b[25@"] = Key{Type: KeyF13, Mod: ModShift | ModCtrl} + table["\x1b[26@"] = Key{Type: KeyF14, Mod: ModShift | ModCtrl} + table["\x1b[28@"] = Key{Type: KeyF15, Mod: ModShift | ModCtrl} + table["\x1b[29@"] = Key{Type: KeyF16, Mod: ModShift | ModCtrl} + table["\x1b[31@"] = Key{Type: KeyF17, Mod: ModShift | ModCtrl} + table["\x1b[32@"] = Key{Type: KeyF18, Mod: ModShift | ModCtrl} + table["\x1b[33@"] = Key{Type: KeyF19, Mod: ModShift | ModCtrl} + table["\x1b[34@"] = Key{Type: KeyF20, Mod: ModShift | ModCtrl} // Register Alt + combinations // XXX: this must come after URxvt but before XTerm keys to register URxvt @@ -312,34 +312,34 @@ func buildKeysTable(flags int, term string) map[string]Key { // These are defined in XTerm // Taken from Foot keymap.h and XTerm modifyOtherKeys // https://codeberg.org/dnkl/foot/src/branch/master/keymap.h - "M": {Sym: KeyKpEnter}, "X": {Sym: KeyKpEqual}, - "j": {Sym: KeyKpMultiply}, "k": {Sym: KeyKpPlus}, - "l": {Sym: KeyKpComma}, "m": {Sym: KeyKpMinus}, - "n": {Sym: KeyKpDecimal}, "o": {Sym: KeyKpDivide}, - "p": {Sym: KeyKp0}, "q": {Sym: KeyKp1}, - "r": {Sym: KeyKp2}, "s": {Sym: KeyKp3}, - "t": {Sym: KeyKp4}, "u": {Sym: KeyKp5}, - "v": {Sym: KeyKp6}, "w": {Sym: KeyKp7}, - "x": {Sym: KeyKp8}, "y": {Sym: KeyKp9}, + "M": {Type: KeyKpEnter}, "X": {Type: KeyKpEqual}, + "j": {Type: KeyKpMultiply}, "k": {Type: KeyKpPlus}, + "l": {Type: KeyKpComma}, "m": {Type: KeyKpMinus}, + "n": {Type: KeyKpDecimal}, "o": {Type: KeyKpDivide}, + "p": {Type: KeyKp0}, "q": {Type: KeyKp1}, + "r": {Type: KeyKp2}, "s": {Type: KeyKp3}, + "t": {Type: KeyKp4}, "u": {Type: KeyKp5}, + "v": {Type: KeyKp6}, "w": {Type: KeyKp7}, + "x": {Type: KeyKp8}, "y": {Type: KeyKp9}, } // XTerm keys csiFuncKeys := map[string]Key{ - "A": {Sym: KeyUp}, "B": {Sym: KeyDown}, - "C": {Sym: KeyRight}, "D": {Sym: KeyLeft}, - "E": {Sym: KeyBegin}, "F": {Sym: KeyEnd}, - "H": {Sym: KeyHome}, "P": {Sym: KeyF1}, - "Q": {Sym: KeyF2}, "R": {Sym: KeyF3}, - "S": {Sym: KeyF4}, + "A": {Type: KeyUp}, "B": {Type: KeyDown}, + "C": {Type: KeyRight}, "D": {Type: KeyLeft}, + "E": {Type: KeyBegin}, "F": {Type: KeyEnd}, + "H": {Type: KeyHome}, "P": {Type: KeyF1}, + "Q": {Type: KeyF2}, "R": {Type: KeyF3}, + "S": {Type: KeyF4}, } // CSI 27 ; ; ~ keys defined in XTerm modifyOtherKeys modifyOtherKeys := map[int]Key{ - ansi.BS: {Sym: KeyBackspace}, - ansi.HT: {Sym: KeyTab}, - ansi.CR: {Sym: KeyEnter}, - ansi.ESC: {Sym: KeyEscape}, - ansi.DEL: {Sym: KeyBackspace}, + ansi.BS: {Type: KeyBackspace}, + ansi.HT: {Type: KeyTab}, + ansi.CR: {Type: KeyEnter}, + ansi.ESC: {Type: KeyEscape}, + ansi.DEL: {Type: KeyBackspace}, } for _, m := range modifiers { diff --git a/terminfo.go b/terminfo.go index eb9cb3c71d..e4be0ddf3e 100644 --- a/terminfo.go +++ b/terminfo.go @@ -56,91 +56,91 @@ func buildTerminfoKeys(flags int, term string) map[string]Key { // See https://github.com/mirror/ncurses/blob/master/include/Caps-ncurses func defaultTerminfoKeys(flags int) map[string]Key { keys := map[string]Key{ - "kcuu1": {Sym: KeyUp}, - "kUP": {Sym: KeyUp, Mod: ModShift}, - "kUP3": {Sym: KeyUp, Mod: ModAlt}, - "kUP4": {Sym: KeyUp, Mod: ModShift | ModAlt}, - "kUP5": {Sym: KeyUp, Mod: ModCtrl}, - "kUP6": {Sym: KeyUp, Mod: ModShift | ModCtrl}, - "kUP7": {Sym: KeyUp, Mod: ModAlt | ModCtrl}, - "kUP8": {Sym: KeyUp, Mod: ModShift | ModAlt | ModCtrl}, - "kcud1": {Sym: KeyDown}, - "kDN": {Sym: KeyDown, Mod: ModShift}, - "kDN3": {Sym: KeyDown, Mod: ModAlt}, - "kDN4": {Sym: KeyDown, Mod: ModShift | ModAlt}, - "kDN5": {Sym: KeyDown, Mod: ModCtrl}, - "kDN7": {Sym: KeyDown, Mod: ModAlt | ModCtrl}, - "kDN6": {Sym: KeyDown, Mod: ModShift | ModCtrl}, - "kDN8": {Sym: KeyDown, Mod: ModShift | ModAlt | ModCtrl}, - "kcub1": {Sym: KeyLeft}, - "kLFT": {Sym: KeyLeft, Mod: ModShift}, - "kLFT3": {Sym: KeyLeft, Mod: ModAlt}, - "kLFT4": {Sym: KeyLeft, Mod: ModShift | ModAlt}, - "kLFT5": {Sym: KeyLeft, Mod: ModCtrl}, - "kLFT6": {Sym: KeyLeft, Mod: ModShift | ModCtrl}, - "kLFT7": {Sym: KeyLeft, Mod: ModAlt | ModCtrl}, - "kLFT8": {Sym: KeyLeft, Mod: ModShift | ModAlt | ModCtrl}, - "kcuf1": {Sym: KeyRight}, - "kRIT": {Sym: KeyRight, Mod: ModShift}, - "kRIT3": {Sym: KeyRight, Mod: ModAlt}, - "kRIT4": {Sym: KeyRight, Mod: ModShift | ModAlt}, - "kRIT5": {Sym: KeyRight, Mod: ModCtrl}, - "kRIT6": {Sym: KeyRight, Mod: ModShift | ModCtrl}, - "kRIT7": {Sym: KeyRight, Mod: ModAlt | ModCtrl}, - "kRIT8": {Sym: KeyRight, Mod: ModShift | ModAlt | ModCtrl}, - "kich1": {Sym: KeyInsert}, - "kIC": {Sym: KeyInsert, Mod: ModShift}, - "kIC3": {Sym: KeyInsert, Mod: ModAlt}, - "kIC4": {Sym: KeyInsert, Mod: ModShift | ModAlt}, - "kIC5": {Sym: KeyInsert, Mod: ModCtrl}, - "kIC6": {Sym: KeyInsert, Mod: ModShift | ModCtrl}, - "kIC7": {Sym: KeyInsert, Mod: ModAlt | ModCtrl}, - "kIC8": {Sym: KeyInsert, Mod: ModShift | ModAlt | ModCtrl}, - "kdch1": {Sym: KeyDelete}, - "kDC": {Sym: KeyDelete, Mod: ModShift}, - "kDC3": {Sym: KeyDelete, Mod: ModAlt}, - "kDC4": {Sym: KeyDelete, Mod: ModShift | ModAlt}, - "kDC5": {Sym: KeyDelete, Mod: ModCtrl}, - "kDC6": {Sym: KeyDelete, Mod: ModShift | ModCtrl}, - "kDC7": {Sym: KeyDelete, Mod: ModAlt | ModCtrl}, - "kDC8": {Sym: KeyDelete, Mod: ModShift | ModAlt | ModCtrl}, - "khome": {Sym: KeyHome}, - "kHOM": {Sym: KeyHome, Mod: ModShift}, - "kHOM3": {Sym: KeyHome, Mod: ModAlt}, - "kHOM4": {Sym: KeyHome, Mod: ModShift | ModAlt}, - "kHOM5": {Sym: KeyHome, Mod: ModCtrl}, - "kHOM6": {Sym: KeyHome, Mod: ModShift | ModCtrl}, - "kHOM7": {Sym: KeyHome, Mod: ModAlt | ModCtrl}, - "kHOM8": {Sym: KeyHome, Mod: ModShift | ModAlt | ModCtrl}, - "kend": {Sym: KeyEnd}, - "kEND": {Sym: KeyEnd, Mod: ModShift}, - "kEND3": {Sym: KeyEnd, Mod: ModAlt}, - "kEND4": {Sym: KeyEnd, Mod: ModShift | ModAlt}, - "kEND5": {Sym: KeyEnd, Mod: ModCtrl}, - "kEND6": {Sym: KeyEnd, Mod: ModShift | ModCtrl}, - "kEND7": {Sym: KeyEnd, Mod: ModAlt | ModCtrl}, - "kEND8": {Sym: KeyEnd, Mod: ModShift | ModAlt | ModCtrl}, - "kpp": {Sym: KeyPgUp}, - "kprv": {Sym: KeyPgUp}, - "kPRV": {Sym: KeyPgUp, Mod: ModShift}, - "kPRV3": {Sym: KeyPgUp, Mod: ModAlt}, - "kPRV4": {Sym: KeyPgUp, Mod: ModShift | ModAlt}, - "kPRV5": {Sym: KeyPgUp, Mod: ModCtrl}, - "kPRV6": {Sym: KeyPgUp, Mod: ModShift | ModCtrl}, - "kPRV7": {Sym: KeyPgUp, Mod: ModAlt | ModCtrl}, - "kPRV8": {Sym: KeyPgUp, Mod: ModShift | ModAlt | ModCtrl}, - "knp": {Sym: KeyPgDown}, - "knxt": {Sym: KeyPgDown}, - "kNXT": {Sym: KeyPgDown, Mod: ModShift}, - "kNXT3": {Sym: KeyPgDown, Mod: ModAlt}, - "kNXT4": {Sym: KeyPgDown, Mod: ModShift | ModAlt}, - "kNXT5": {Sym: KeyPgDown, Mod: ModCtrl}, - "kNXT6": {Sym: KeyPgDown, Mod: ModShift | ModCtrl}, - "kNXT7": {Sym: KeyPgDown, Mod: ModAlt | ModCtrl}, - "kNXT8": {Sym: KeyPgDown, Mod: ModShift | ModAlt | ModCtrl}, + "kcuu1": {Type: KeyUp}, + "kUP": {Type: KeyUp, Mod: ModShift}, + "kUP3": {Type: KeyUp, Mod: ModAlt}, + "kUP4": {Type: KeyUp, Mod: ModShift | ModAlt}, + "kUP5": {Type: KeyUp, Mod: ModCtrl}, + "kUP6": {Type: KeyUp, Mod: ModShift | ModCtrl}, + "kUP7": {Type: KeyUp, Mod: ModAlt | ModCtrl}, + "kUP8": {Type: KeyUp, Mod: ModShift | ModAlt | ModCtrl}, + "kcud1": {Type: KeyDown}, + "kDN": {Type: KeyDown, Mod: ModShift}, + "kDN3": {Type: KeyDown, Mod: ModAlt}, + "kDN4": {Type: KeyDown, Mod: ModShift | ModAlt}, + "kDN5": {Type: KeyDown, Mod: ModCtrl}, + "kDN7": {Type: KeyDown, Mod: ModAlt | ModCtrl}, + "kDN6": {Type: KeyDown, Mod: ModShift | ModCtrl}, + "kDN8": {Type: KeyDown, Mod: ModShift | ModAlt | ModCtrl}, + "kcub1": {Type: KeyLeft}, + "kLFT": {Type: KeyLeft, Mod: ModShift}, + "kLFT3": {Type: KeyLeft, Mod: ModAlt}, + "kLFT4": {Type: KeyLeft, Mod: ModShift | ModAlt}, + "kLFT5": {Type: KeyLeft, Mod: ModCtrl}, + "kLFT6": {Type: KeyLeft, Mod: ModShift | ModCtrl}, + "kLFT7": {Type: KeyLeft, Mod: ModAlt | ModCtrl}, + "kLFT8": {Type: KeyLeft, Mod: ModShift | ModAlt | ModCtrl}, + "kcuf1": {Type: KeyRight}, + "kRIT": {Type: KeyRight, Mod: ModShift}, + "kRIT3": {Type: KeyRight, Mod: ModAlt}, + "kRIT4": {Type: KeyRight, Mod: ModShift | ModAlt}, + "kRIT5": {Type: KeyRight, Mod: ModCtrl}, + "kRIT6": {Type: KeyRight, Mod: ModShift | ModCtrl}, + "kRIT7": {Type: KeyRight, Mod: ModAlt | ModCtrl}, + "kRIT8": {Type: KeyRight, Mod: ModShift | ModAlt | ModCtrl}, + "kich1": {Type: KeyInsert}, + "kIC": {Type: KeyInsert, Mod: ModShift}, + "kIC3": {Type: KeyInsert, Mod: ModAlt}, + "kIC4": {Type: KeyInsert, Mod: ModShift | ModAlt}, + "kIC5": {Type: KeyInsert, Mod: ModCtrl}, + "kIC6": {Type: KeyInsert, Mod: ModShift | ModCtrl}, + "kIC7": {Type: KeyInsert, Mod: ModAlt | ModCtrl}, + "kIC8": {Type: KeyInsert, Mod: ModShift | ModAlt | ModCtrl}, + "kdch1": {Type: KeyDelete}, + "kDC": {Type: KeyDelete, Mod: ModShift}, + "kDC3": {Type: KeyDelete, Mod: ModAlt}, + "kDC4": {Type: KeyDelete, Mod: ModShift | ModAlt}, + "kDC5": {Type: KeyDelete, Mod: ModCtrl}, + "kDC6": {Type: KeyDelete, Mod: ModShift | ModCtrl}, + "kDC7": {Type: KeyDelete, Mod: ModAlt | ModCtrl}, + "kDC8": {Type: KeyDelete, Mod: ModShift | ModAlt | ModCtrl}, + "khome": {Type: KeyHome}, + "kHOM": {Type: KeyHome, Mod: ModShift}, + "kHOM3": {Type: KeyHome, Mod: ModAlt}, + "kHOM4": {Type: KeyHome, Mod: ModShift | ModAlt}, + "kHOM5": {Type: KeyHome, Mod: ModCtrl}, + "kHOM6": {Type: KeyHome, Mod: ModShift | ModCtrl}, + "kHOM7": {Type: KeyHome, Mod: ModAlt | ModCtrl}, + "kHOM8": {Type: KeyHome, Mod: ModShift | ModAlt | ModCtrl}, + "kend": {Type: KeyEnd}, + "kEND": {Type: KeyEnd, Mod: ModShift}, + "kEND3": {Type: KeyEnd, Mod: ModAlt}, + "kEND4": {Type: KeyEnd, Mod: ModShift | ModAlt}, + "kEND5": {Type: KeyEnd, Mod: ModCtrl}, + "kEND6": {Type: KeyEnd, Mod: ModShift | ModCtrl}, + "kEND7": {Type: KeyEnd, Mod: ModAlt | ModCtrl}, + "kEND8": {Type: KeyEnd, Mod: ModShift | ModAlt | ModCtrl}, + "kpp": {Type: KeyPgUp}, + "kprv": {Type: KeyPgUp}, + "kPRV": {Type: KeyPgUp, Mod: ModShift}, + "kPRV3": {Type: KeyPgUp, Mod: ModAlt}, + "kPRV4": {Type: KeyPgUp, Mod: ModShift | ModAlt}, + "kPRV5": {Type: KeyPgUp, Mod: ModCtrl}, + "kPRV6": {Type: KeyPgUp, Mod: ModShift | ModCtrl}, + "kPRV7": {Type: KeyPgUp, Mod: ModAlt | ModCtrl}, + "kPRV8": {Type: KeyPgUp, Mod: ModShift | ModAlt | ModCtrl}, + "knp": {Type: KeyPgDown}, + "knxt": {Type: KeyPgDown}, + "kNXT": {Type: KeyPgDown, Mod: ModShift}, + "kNXT3": {Type: KeyPgDown, Mod: ModAlt}, + "kNXT4": {Type: KeyPgDown, Mod: ModShift | ModAlt}, + "kNXT5": {Type: KeyPgDown, Mod: ModCtrl}, + "kNXT6": {Type: KeyPgDown, Mod: ModShift | ModCtrl}, + "kNXT7": {Type: KeyPgDown, Mod: ModAlt | ModCtrl}, + "kNXT8": {Type: KeyPgDown, Mod: ModShift | ModAlt | ModCtrl}, - "kbs": {Sym: KeyBackspace}, - "kcbt": {Sym: KeyTab, Mod: ModShift}, + "kbs": {Type: KeyBackspace}, + "kcbt": {Type: KeyTab, Mod: ModShift}, // Function keys // This only includes the first 12 function keys. The rest are treated @@ -152,125 +152,125 @@ func defaultTerminfoKeys(flags int) map[string]Key { // See https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyFunctionKeys // See https://invisible-island.net/xterm/terminfo.html - "kf1": {Sym: KeyF1}, - "kf2": {Sym: KeyF2}, - "kf3": {Sym: KeyF3}, - "kf4": {Sym: KeyF4}, - "kf5": {Sym: KeyF5}, - "kf6": {Sym: KeyF6}, - "kf7": {Sym: KeyF7}, - "kf8": {Sym: KeyF8}, - "kf9": {Sym: KeyF9}, - "kf10": {Sym: KeyF10}, - "kf11": {Sym: KeyF11}, - "kf12": {Sym: KeyF12}, - "kf13": {Sym: KeyF1, Mod: ModShift}, - "kf14": {Sym: KeyF2, Mod: ModShift}, - "kf15": {Sym: KeyF3, Mod: ModShift}, - "kf16": {Sym: KeyF4, Mod: ModShift}, - "kf17": {Sym: KeyF5, Mod: ModShift}, - "kf18": {Sym: KeyF6, Mod: ModShift}, - "kf19": {Sym: KeyF7, Mod: ModShift}, - "kf20": {Sym: KeyF8, Mod: ModShift}, - "kf21": {Sym: KeyF9, Mod: ModShift}, - "kf22": {Sym: KeyF10, Mod: ModShift}, - "kf23": {Sym: KeyF11, Mod: ModShift}, - "kf24": {Sym: KeyF12, Mod: ModShift}, - "kf25": {Sym: KeyF1, Mod: ModCtrl}, - "kf26": {Sym: KeyF2, Mod: ModCtrl}, - "kf27": {Sym: KeyF3, Mod: ModCtrl}, - "kf28": {Sym: KeyF4, Mod: ModCtrl}, - "kf29": {Sym: KeyF5, Mod: ModCtrl}, - "kf30": {Sym: KeyF6, Mod: ModCtrl}, - "kf31": {Sym: KeyF7, Mod: ModCtrl}, - "kf32": {Sym: KeyF8, Mod: ModCtrl}, - "kf33": {Sym: KeyF9, Mod: ModCtrl}, - "kf34": {Sym: KeyF10, Mod: ModCtrl}, - "kf35": {Sym: KeyF11, Mod: ModCtrl}, - "kf36": {Sym: KeyF12, Mod: ModCtrl}, - "kf37": {Sym: KeyF1, Mod: ModShift | ModCtrl}, - "kf38": {Sym: KeyF2, Mod: ModShift | ModCtrl}, - "kf39": {Sym: KeyF3, Mod: ModShift | ModCtrl}, - "kf40": {Sym: KeyF4, Mod: ModShift | ModCtrl}, - "kf41": {Sym: KeyF5, Mod: ModShift | ModCtrl}, - "kf42": {Sym: KeyF6, Mod: ModShift | ModCtrl}, - "kf43": {Sym: KeyF7, Mod: ModShift | ModCtrl}, - "kf44": {Sym: KeyF8, Mod: ModShift | ModCtrl}, - "kf45": {Sym: KeyF9, Mod: ModShift | ModCtrl}, - "kf46": {Sym: KeyF10, Mod: ModShift | ModCtrl}, - "kf47": {Sym: KeyF11, Mod: ModShift | ModCtrl}, - "kf48": {Sym: KeyF12, Mod: ModShift | ModCtrl}, - "kf49": {Sym: KeyF1, Mod: ModAlt}, - "kf50": {Sym: KeyF2, Mod: ModAlt}, - "kf51": {Sym: KeyF3, Mod: ModAlt}, - "kf52": {Sym: KeyF4, Mod: ModAlt}, - "kf53": {Sym: KeyF5, Mod: ModAlt}, - "kf54": {Sym: KeyF6, Mod: ModAlt}, - "kf55": {Sym: KeyF7, Mod: ModAlt}, - "kf56": {Sym: KeyF8, Mod: ModAlt}, - "kf57": {Sym: KeyF9, Mod: ModAlt}, - "kf58": {Sym: KeyF10, Mod: ModAlt}, - "kf59": {Sym: KeyF11, Mod: ModAlt}, - "kf60": {Sym: KeyF12, Mod: ModAlt}, - "kf61": {Sym: KeyF1, Mod: ModShift | ModAlt}, - "kf62": {Sym: KeyF2, Mod: ModShift | ModAlt}, - "kf63": {Sym: KeyF3, Mod: ModShift | ModAlt}, + "kf1": {Type: KeyF1}, + "kf2": {Type: KeyF2}, + "kf3": {Type: KeyF3}, + "kf4": {Type: KeyF4}, + "kf5": {Type: KeyF5}, + "kf6": {Type: KeyF6}, + "kf7": {Type: KeyF7}, + "kf8": {Type: KeyF8}, + "kf9": {Type: KeyF9}, + "kf10": {Type: KeyF10}, + "kf11": {Type: KeyF11}, + "kf12": {Type: KeyF12}, + "kf13": {Type: KeyF1, Mod: ModShift}, + "kf14": {Type: KeyF2, Mod: ModShift}, + "kf15": {Type: KeyF3, Mod: ModShift}, + "kf16": {Type: KeyF4, Mod: ModShift}, + "kf17": {Type: KeyF5, Mod: ModShift}, + "kf18": {Type: KeyF6, Mod: ModShift}, + "kf19": {Type: KeyF7, Mod: ModShift}, + "kf20": {Type: KeyF8, Mod: ModShift}, + "kf21": {Type: KeyF9, Mod: ModShift}, + "kf22": {Type: KeyF10, Mod: ModShift}, + "kf23": {Type: KeyF11, Mod: ModShift}, + "kf24": {Type: KeyF12, Mod: ModShift}, + "kf25": {Type: KeyF1, Mod: ModCtrl}, + "kf26": {Type: KeyF2, Mod: ModCtrl}, + "kf27": {Type: KeyF3, Mod: ModCtrl}, + "kf28": {Type: KeyF4, Mod: ModCtrl}, + "kf29": {Type: KeyF5, Mod: ModCtrl}, + "kf30": {Type: KeyF6, Mod: ModCtrl}, + "kf31": {Type: KeyF7, Mod: ModCtrl}, + "kf32": {Type: KeyF8, Mod: ModCtrl}, + "kf33": {Type: KeyF9, Mod: ModCtrl}, + "kf34": {Type: KeyF10, Mod: ModCtrl}, + "kf35": {Type: KeyF11, Mod: ModCtrl}, + "kf36": {Type: KeyF12, Mod: ModCtrl}, + "kf37": {Type: KeyF1, Mod: ModShift | ModCtrl}, + "kf38": {Type: KeyF2, Mod: ModShift | ModCtrl}, + "kf39": {Type: KeyF3, Mod: ModShift | ModCtrl}, + "kf40": {Type: KeyF4, Mod: ModShift | ModCtrl}, + "kf41": {Type: KeyF5, Mod: ModShift | ModCtrl}, + "kf42": {Type: KeyF6, Mod: ModShift | ModCtrl}, + "kf43": {Type: KeyF7, Mod: ModShift | ModCtrl}, + "kf44": {Type: KeyF8, Mod: ModShift | ModCtrl}, + "kf45": {Type: KeyF9, Mod: ModShift | ModCtrl}, + "kf46": {Type: KeyF10, Mod: ModShift | ModCtrl}, + "kf47": {Type: KeyF11, Mod: ModShift | ModCtrl}, + "kf48": {Type: KeyF12, Mod: ModShift | ModCtrl}, + "kf49": {Type: KeyF1, Mod: ModAlt}, + "kf50": {Type: KeyF2, Mod: ModAlt}, + "kf51": {Type: KeyF3, Mod: ModAlt}, + "kf52": {Type: KeyF4, Mod: ModAlt}, + "kf53": {Type: KeyF5, Mod: ModAlt}, + "kf54": {Type: KeyF6, Mod: ModAlt}, + "kf55": {Type: KeyF7, Mod: ModAlt}, + "kf56": {Type: KeyF8, Mod: ModAlt}, + "kf57": {Type: KeyF9, Mod: ModAlt}, + "kf58": {Type: KeyF10, Mod: ModAlt}, + "kf59": {Type: KeyF11, Mod: ModAlt}, + "kf60": {Type: KeyF12, Mod: ModAlt}, + "kf61": {Type: KeyF1, Mod: ModShift | ModAlt}, + "kf62": {Type: KeyF2, Mod: ModShift | ModAlt}, + "kf63": {Type: KeyF3, Mod: ModShift | ModAlt}, } // Preserve F keys from F13 to F63 instead of using them for F-keys // modifiers. if flags&_FlagFKeys != 0 { - keys["kf13"] = Key{Sym: KeyF13} - keys["kf14"] = Key{Sym: KeyF14} - keys["kf15"] = Key{Sym: KeyF15} - keys["kf16"] = Key{Sym: KeyF16} - keys["kf17"] = Key{Sym: KeyF17} - keys["kf18"] = Key{Sym: KeyF18} - keys["kf19"] = Key{Sym: KeyF19} - keys["kf20"] = Key{Sym: KeyF20} - keys["kf21"] = Key{Sym: KeyF21} - keys["kf22"] = Key{Sym: KeyF22} - keys["kf23"] = Key{Sym: KeyF23} - keys["kf24"] = Key{Sym: KeyF24} - keys["kf25"] = Key{Sym: KeyF25} - keys["kf26"] = Key{Sym: KeyF26} - keys["kf27"] = Key{Sym: KeyF27} - keys["kf28"] = Key{Sym: KeyF28} - keys["kf29"] = Key{Sym: KeyF29} - keys["kf30"] = Key{Sym: KeyF30} - keys["kf31"] = Key{Sym: KeyF31} - keys["kf32"] = Key{Sym: KeyF32} - keys["kf33"] = Key{Sym: KeyF33} - keys["kf34"] = Key{Sym: KeyF34} - keys["kf35"] = Key{Sym: KeyF35} - keys["kf36"] = Key{Sym: KeyF36} - keys["kf37"] = Key{Sym: KeyF37} - keys["kf38"] = Key{Sym: KeyF38} - keys["kf39"] = Key{Sym: KeyF39} - keys["kf40"] = Key{Sym: KeyF40} - keys["kf41"] = Key{Sym: KeyF41} - keys["kf42"] = Key{Sym: KeyF42} - keys["kf43"] = Key{Sym: KeyF43} - keys["kf44"] = Key{Sym: KeyF44} - keys["kf45"] = Key{Sym: KeyF45} - keys["kf46"] = Key{Sym: KeyF46} - keys["kf47"] = Key{Sym: KeyF47} - keys["kf48"] = Key{Sym: KeyF48} - keys["kf49"] = Key{Sym: KeyF49} - keys["kf50"] = Key{Sym: KeyF50} - keys["kf51"] = Key{Sym: KeyF51} - keys["kf52"] = Key{Sym: KeyF52} - keys["kf53"] = Key{Sym: KeyF53} - keys["kf54"] = Key{Sym: KeyF54} - keys["kf55"] = Key{Sym: KeyF55} - keys["kf56"] = Key{Sym: KeyF56} - keys["kf57"] = Key{Sym: KeyF57} - keys["kf58"] = Key{Sym: KeyF58} - keys["kf59"] = Key{Sym: KeyF59} - keys["kf60"] = Key{Sym: KeyF60} - keys["kf61"] = Key{Sym: KeyF61} - keys["kf62"] = Key{Sym: KeyF62} - keys["kf63"] = Key{Sym: KeyF63} + keys["kf13"] = Key{Type: KeyF13} + keys["kf14"] = Key{Type: KeyF14} + keys["kf15"] = Key{Type: KeyF15} + keys["kf16"] = Key{Type: KeyF16} + keys["kf17"] = Key{Type: KeyF17} + keys["kf18"] = Key{Type: KeyF18} + keys["kf19"] = Key{Type: KeyF19} + keys["kf20"] = Key{Type: KeyF20} + keys["kf21"] = Key{Type: KeyF21} + keys["kf22"] = Key{Type: KeyF22} + keys["kf23"] = Key{Type: KeyF23} + keys["kf24"] = Key{Type: KeyF24} + keys["kf25"] = Key{Type: KeyF25} + keys["kf26"] = Key{Type: KeyF26} + keys["kf27"] = Key{Type: KeyF27} + keys["kf28"] = Key{Type: KeyF28} + keys["kf29"] = Key{Type: KeyF29} + keys["kf30"] = Key{Type: KeyF30} + keys["kf31"] = Key{Type: KeyF31} + keys["kf32"] = Key{Type: KeyF32} + keys["kf33"] = Key{Type: KeyF33} + keys["kf34"] = Key{Type: KeyF34} + keys["kf35"] = Key{Type: KeyF35} + keys["kf36"] = Key{Type: KeyF36} + keys["kf37"] = Key{Type: KeyF37} + keys["kf38"] = Key{Type: KeyF38} + keys["kf39"] = Key{Type: KeyF39} + keys["kf40"] = Key{Type: KeyF40} + keys["kf41"] = Key{Type: KeyF41} + keys["kf42"] = Key{Type: KeyF42} + keys["kf43"] = Key{Type: KeyF43} + keys["kf44"] = Key{Type: KeyF44} + keys["kf45"] = Key{Type: KeyF45} + keys["kf46"] = Key{Type: KeyF46} + keys["kf47"] = Key{Type: KeyF47} + keys["kf48"] = Key{Type: KeyF48} + keys["kf49"] = Key{Type: KeyF49} + keys["kf50"] = Key{Type: KeyF50} + keys["kf51"] = Key{Type: KeyF51} + keys["kf52"] = Key{Type: KeyF52} + keys["kf53"] = Key{Type: KeyF53} + keys["kf54"] = Key{Type: KeyF54} + keys["kf55"] = Key{Type: KeyF55} + keys["kf56"] = Key{Type: KeyF56} + keys["kf57"] = Key{Type: KeyF57} + keys["kf58"] = Key{Type: KeyF58} + keys["kf59"] = Key{Type: KeyF59} + keys["kf60"] = Key{Type: KeyF60} + keys["kf61"] = Key{Type: KeyF61} + keys["kf62"] = Key{Type: KeyF62} + keys["kf63"] = Key{Type: KeyF63} } return keys diff --git a/tty.go b/tty.go index 304bb29166..9d5612cfbb 100644 --- a/tty.go +++ b/tty.go @@ -118,23 +118,23 @@ func readInputs(ctx context.Context, msgs chan<- Msg, reader *driver) error { k := KeyMsg{ Alt: e.Mod.HasAlt(), Runes: e.Runes, - Type: e.Sym, + Type: e.Type, } // Backwards compatibility for ctrl- and shift- keys switch { case e.Mod.HasCtrl() && e.Mod.HasShift(): - switch e.Sym { + switch e.Type { case KeyUp, KeyDown, KeyRight, KeyLeft: k.Runes = nil - k.Type = KeyCtrlShiftUp - e.Sym + KeyUp + k.Type = KeyCtrlShiftUp - e.Type + KeyUp case KeyHome, KeyEnd: k.Runes = nil - k.Type = KeyCtrlShiftHome - e.Sym + KeyHome + k.Type = KeyCtrlShiftHome - e.Type + KeyHome } case e.Mod.HasCtrl(): - switch e.Sym { - case KeyNone: // KeyRunes + switch e.Type { + case KeyRunes: // KeyRunes switch r := e.Rune(); r { case ' ': k.Runes = nil @@ -153,28 +153,28 @@ func readInputs(ctx context.Context, msgs chan<- Msg, reader *driver) error { } case KeyPgUp, KeyPgDown, KeyHome, KeyEnd: k.Runes = nil - k.Type = KeyCtrlPgUp - e.Sym + KeyPgUp + k.Type = KeyCtrlPgUp - e.Type + KeyPgUp case KeyUp, KeyDown, KeyRight, KeyLeft: k.Runes = nil - k.Type = KeyCtrlUp - e.Sym + KeyUp + k.Type = KeyCtrlUp - e.Type + KeyUp } case e.Mod.HasShift(): - switch e.Sym { + switch e.Type { case KeyTab: k.Runes = nil k.Type = KeyShiftTab case KeyUp, KeyDown, KeyRight, KeyLeft: k.Runes = nil - k.Type = KeyShiftUp - e.Sym + KeyUp + k.Type = KeyShiftUp - e.Type + KeyUp k.Runes = nil case KeyHome, KeyEnd: k.Runes = nil - k.Type = KeyShiftHome - e.Sym + KeyHome + k.Type = KeyShiftHome - e.Type + KeyHome } } switch k.Type { - case KeyNone: // KeyRunes + case KeyRunes: // KeyRunes if len(k.Runes) > 0 { incomingMsgs = append(incomingMsgs, k) } diff --git a/win32input.go b/win32input.go index 5d8b9902c7..526f61aba0 100644 --- a/win32input.go +++ b/win32input.go @@ -15,22 +15,22 @@ func parseWin32InputKeyEvent(vkc coninput.VirtualKeyCode, _ coninput.VirtualKeyC return nil case coninput.VK_MENU: if cks.Contains(coninput.LEFT_ALT_PRESSED) { - key = Key{Sym: KeyLeftAlt} + key = Key{Type: KeyLeftAlt} } else if cks.Contains(coninput.RIGHT_ALT_PRESSED) { - key = Key{Sym: KeyRightAlt} + key = Key{Type: KeyRightAlt} } else if !keyDown { return nil } case coninput.VK_CONTROL: if cks.Contains(coninput.LEFT_CTRL_PRESSED) { - key = Key{Sym: KeyLeftCtrl} + key = Key{Type: KeyLeftCtrl} } else if cks.Contains(coninput.RIGHT_CTRL_PRESSED) { - key = Key{Sym: KeyRightCtrl} + key = Key{Type: KeyRightCtrl} } else if !keyDown { return nil } case coninput.VK_CAPITAL: - key = Key{Sym: KeyCapsLock} + key = Key{Type: KeyCapsLock} default: var ok bool key, ok = vkKeyEvent[vkc] @@ -88,74 +88,74 @@ func parseWin32InputKeyEvent(vkc coninput.VirtualKeyCode, _ coninput.VirtualKeyC } var vkKeyEvent = map[coninput.VirtualKeyCode]Key{ - coninput.VK_RETURN: {Sym: KeyEnter}, - coninput.VK_BACK: {Sym: KeyBackspace}, - coninput.VK_TAB: {Sym: KeyTab}, - coninput.VK_ESCAPE: {Sym: KeyEscape}, - coninput.VK_SPACE: {Sym: KeySpace, Runes: []rune{' '}}, - coninput.VK_UP: {Sym: KeyUp}, - coninput.VK_DOWN: {Sym: KeyDown}, - coninput.VK_RIGHT: {Sym: KeyRight}, - coninput.VK_LEFT: {Sym: KeyLeft}, - coninput.VK_HOME: {Sym: KeyHome}, - coninput.VK_END: {Sym: KeyEnd}, - coninput.VK_PRIOR: {Sym: KeyPgUp}, - coninput.VK_NEXT: {Sym: KeyPgDown}, - coninput.VK_DELETE: {Sym: KeyDelete}, - coninput.VK_SELECT: {Sym: KeySelect}, - coninput.VK_SNAPSHOT: {Sym: KeyPrintScreen}, - coninput.VK_INSERT: {Sym: KeyInsert}, - coninput.VK_LWIN: {Sym: KeyLeftSuper}, - coninput.VK_RWIN: {Sym: KeyRightSuper}, - coninput.VK_APPS: {Sym: KeyMenu}, - coninput.VK_NUMPAD0: {Sym: KeyKp0}, - coninput.VK_NUMPAD1: {Sym: KeyKp1}, - coninput.VK_NUMPAD2: {Sym: KeyKp2}, - coninput.VK_NUMPAD3: {Sym: KeyKp3}, - coninput.VK_NUMPAD4: {Sym: KeyKp4}, - coninput.VK_NUMPAD5: {Sym: KeyKp5}, - coninput.VK_NUMPAD6: {Sym: KeyKp6}, - coninput.VK_NUMPAD7: {Sym: KeyKp7}, - coninput.VK_NUMPAD8: {Sym: KeyKp8}, - coninput.VK_NUMPAD9: {Sym: KeyKp9}, - coninput.VK_MULTIPLY: {Sym: KeyKpMultiply}, - coninput.VK_ADD: {Sym: KeyKpPlus}, - coninput.VK_SEPARATOR: {Sym: KeyKpComma}, - coninput.VK_SUBTRACT: {Sym: KeyKpMinus}, - coninput.VK_DECIMAL: {Sym: KeyKpDecimal}, - coninput.VK_DIVIDE: {Sym: KeyKpDivide}, - coninput.VK_F1: {Sym: KeyF1}, - coninput.VK_F2: {Sym: KeyF2}, - coninput.VK_F3: {Sym: KeyF3}, - coninput.VK_F4: {Sym: KeyF4}, - coninput.VK_F5: {Sym: KeyF5}, - coninput.VK_F6: {Sym: KeyF6}, - coninput.VK_F7: {Sym: KeyF7}, - coninput.VK_F8: {Sym: KeyF8}, - coninput.VK_F9: {Sym: KeyF9}, - coninput.VK_F10: {Sym: KeyF10}, - coninput.VK_F11: {Sym: KeyF11}, - coninput.VK_F12: {Sym: KeyF12}, - coninput.VK_F13: {Sym: KeyF13}, - coninput.VK_F14: {Sym: KeyF14}, - coninput.VK_F15: {Sym: KeyF15}, - coninput.VK_F16: {Sym: KeyF16}, - coninput.VK_F17: {Sym: KeyF17}, - coninput.VK_F18: {Sym: KeyF18}, - coninput.VK_F19: {Sym: KeyF19}, - coninput.VK_F20: {Sym: KeyF20}, - coninput.VK_F21: {Sym: KeyF21}, - coninput.VK_F22: {Sym: KeyF22}, - coninput.VK_F23: {Sym: KeyF23}, - coninput.VK_F24: {Sym: KeyF24}, - coninput.VK_NUMLOCK: {Sym: KeyNumLock}, - coninput.VK_SCROLL: {Sym: KeyScrollLock}, - coninput.VK_LSHIFT: {Sym: KeyLeftShift}, - coninput.VK_RSHIFT: {Sym: KeyRightShift}, - coninput.VK_LCONTROL: {Sym: KeyLeftCtrl}, - coninput.VK_RCONTROL: {Sym: KeyRightCtrl}, - coninput.VK_LMENU: {Sym: KeyLeftAlt}, - coninput.VK_RMENU: {Sym: KeyRightAlt}, + coninput.VK_RETURN: {Type: KeyEnter}, + coninput.VK_BACK: {Type: KeyBackspace}, + coninput.VK_TAB: {Type: KeyTab}, + coninput.VK_ESCAPE: {Type: KeyEscape}, + coninput.VK_SPACE: {Type: KeySpace, Runes: []rune{' '}}, + coninput.VK_UP: {Type: KeyUp}, + coninput.VK_DOWN: {Type: KeyDown}, + coninput.VK_RIGHT: {Type: KeyRight}, + coninput.VK_LEFT: {Type: KeyLeft}, + coninput.VK_HOME: {Type: KeyHome}, + coninput.VK_END: {Type: KeyEnd}, + coninput.VK_PRIOR: {Type: KeyPgUp}, + coninput.VK_NEXT: {Type: KeyPgDown}, + coninput.VK_DELETE: {Type: KeyDelete}, + coninput.VK_SELECT: {Type: KeySelect}, + coninput.VK_SNAPSHOT: {Type: KeyPrintScreen}, + coninput.VK_INSERT: {Type: KeyInsert}, + coninput.VK_LWIN: {Type: KeyLeftSuper}, + coninput.VK_RWIN: {Type: KeyRightSuper}, + coninput.VK_APPS: {Type: KeyMenu}, + coninput.VK_NUMPAD0: {Type: KeyKp0}, + coninput.VK_NUMPAD1: {Type: KeyKp1}, + coninput.VK_NUMPAD2: {Type: KeyKp2}, + coninput.VK_NUMPAD3: {Type: KeyKp3}, + coninput.VK_NUMPAD4: {Type: KeyKp4}, + coninput.VK_NUMPAD5: {Type: KeyKp5}, + coninput.VK_NUMPAD6: {Type: KeyKp6}, + coninput.VK_NUMPAD7: {Type: KeyKp7}, + coninput.VK_NUMPAD8: {Type: KeyKp8}, + coninput.VK_NUMPAD9: {Type: KeyKp9}, + coninput.VK_MULTIPLY: {Type: KeyKpMultiply}, + coninput.VK_ADD: {Type: KeyKpPlus}, + coninput.VK_SEPARATOR: {Type: KeyKpComma}, + coninput.VK_SUBTRACT: {Type: KeyKpMinus}, + coninput.VK_DECIMAL: {Type: KeyKpDecimal}, + coninput.VK_DIVIDE: {Type: KeyKpDivide}, + coninput.VK_F1: {Type: KeyF1}, + coninput.VK_F2: {Type: KeyF2}, + coninput.VK_F3: {Type: KeyF3}, + coninput.VK_F4: {Type: KeyF4}, + coninput.VK_F5: {Type: KeyF5}, + coninput.VK_F6: {Type: KeyF6}, + coninput.VK_F7: {Type: KeyF7}, + coninput.VK_F8: {Type: KeyF8}, + coninput.VK_F9: {Type: KeyF9}, + coninput.VK_F10: {Type: KeyF10}, + coninput.VK_F11: {Type: KeyF11}, + coninput.VK_F12: {Type: KeyF12}, + coninput.VK_F13: {Type: KeyF13}, + coninput.VK_F14: {Type: KeyF14}, + coninput.VK_F15: {Type: KeyF15}, + coninput.VK_F16: {Type: KeyF16}, + coninput.VK_F17: {Type: KeyF17}, + coninput.VK_F18: {Type: KeyF18}, + coninput.VK_F19: {Type: KeyF19}, + coninput.VK_F20: {Type: KeyF20}, + coninput.VK_F21: {Type: KeyF21}, + coninput.VK_F22: {Type: KeyF22}, + coninput.VK_F23: {Type: KeyF23}, + coninput.VK_F24: {Type: KeyF24}, + coninput.VK_NUMLOCK: {Type: KeyNumLock}, + coninput.VK_SCROLL: {Type: KeyScrollLock}, + coninput.VK_LSHIFT: {Type: KeyLeftShift}, + coninput.VK_RSHIFT: {Type: KeyRightShift}, + coninput.VK_LCONTROL: {Type: KeyLeftCtrl}, + coninput.VK_RCONTROL: {Type: KeyRightCtrl}, + coninput.VK_LMENU: {Type: KeyLeftAlt}, + coninput.VK_RMENU: {Type: KeyRightAlt}, coninput.VK_OEM_4: {Runes: []rune{'['}}, // TODO: add more keys } diff --git a/xterm.go b/xterm.go index 0c5706f500..f09caeba52 100644 --- a/xterm.go +++ b/xterm.go @@ -11,15 +11,15 @@ func parseXTermModifyOtherKeys(csi *ansi.CsiSequence) Msg { switch r { case ansi.BS: - return KeyPressMsg{Mod: mod, Sym: KeyBackspace} + return KeyPressMsg{Mod: mod, Type: KeyBackspace} case ansi.HT: - return KeyPressMsg{Mod: mod, Sym: KeyTab} + return KeyPressMsg{Mod: mod, Type: KeyTab} case ansi.CR: - return KeyPressMsg{Mod: mod, Sym: KeyEnter} + return KeyPressMsg{Mod: mod, Type: KeyEnter} case ansi.ESC: - return KeyPressMsg{Mod: mod, Sym: KeyEscape} + return KeyPressMsg{Mod: mod, Type: KeyEscape} case ansi.DEL: - return KeyPressMsg{Mod: mod, Sym: KeyBackspace} + return KeyPressMsg{Mod: mod, Type: KeyBackspace} } // CSI 27 ; ; ~ keys defined in XTerm modifyOtherKeys