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.

keys.go · 111 lines · 3.2 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 20h ago1package terminal
2
3import "github.com/gdamore/tcell/v2"
4
5// Encode turns a key press into the bytes a terminal program expects to read.
6//
7// applicationCursor is the screen's DECCKM setting: a program that has asked
8// for application cursor keys expects ESC O A for the up arrow rather than
9// ESC [ A, and gets the arrow keys wrong if it is given the other form.
10//
11// A key with no terminal meaning encodes to nothing at all, which the caller
12// should treat as "nothing to send" rather than as an empty line.
13//
14// terminal.Encode(tcell.NewEventKey(tcell.KeyEnter, 0, tcell.ModNone), false)
15// // []byte{'\r'}
16func Encode(ev *tcell.EventKey, applicationCursor bool) []byte {
17 if sequence, ok := encodeCursor(ev.Key(), applicationCursor); ok {
18 return sequence
19 }
20 if sequence, ok := namedKeys[ev.Key()]; ok {
21 return []byte(sequence)
22 }
23 if ev.Key() == tcell.KeyRune {
24 return encodeRune(ev)
25 }
26 return encodeControl(ev)
27}
28
29// cursorKeys are the four arrows and the two keys that travel with them, whose
30// encoding depends on the mode the program asked for.
31var cursorKeys = map[tcell.Key]byte{
32 tcell.KeyUp: 'A',
33 tcell.KeyDown: 'B',
34 tcell.KeyRight: 'C',
35 tcell.KeyLeft: 'D',
36 tcell.KeyHome: 'H',
37 tcell.KeyEnd: 'F',
38}
39
40// encodeCursor encodes an arrow, Home or End in whichever form the program is
41// expecting.
42func encodeCursor(key tcell.Key, applicationCursor bool) ([]byte, bool) {
43 final, ok := cursorKeys[key]
44 if !ok {
45 return nil, false
46 }
47
48 introducer := byte('[')
49 if applicationCursor {
50 introducer = 'O'
51 }
52 return []byte{escape, introducer, final}, true
53}
54
55// namedKeys are the keys with a fixed sequence of their own.
56var namedKeys = map[tcell.Key]string{
57 tcell.KeyEnter: "\r",
58 tcell.KeyTab: "\t",
59 tcell.KeyEscape: "\x1b",
60 tcell.KeyBackspace: "\x7f",
61 tcell.KeyBackspace2: "\x7f",
62 tcell.KeyBacktab: "\x1b[Z",
63 tcell.KeyInsert: "\x1b[2~",
64 tcell.KeyDelete: "\x1b[3~",
65 tcell.KeyPgUp: "\x1b[5~",
66 tcell.KeyPgDn: "\x1b[6~",
67
68 tcell.KeyF1: "\x1bOP",
69 tcell.KeyF2: "\x1bOQ",
70 tcell.KeyF3: "\x1bOR",
71 tcell.KeyF4: "\x1bOS",
72 tcell.KeyF5: "\x1b[15~",
73 tcell.KeyF6: "\x1b[17~",
74 tcell.KeyF7: "\x1b[18~",
75 tcell.KeyF8: "\x1b[19~",
76 tcell.KeyF9: "\x1b[20~",
77 tcell.KeyF10: "\x1b[21~",
78 tcell.KeyF11: "\x1b[23~",
79 tcell.KeyF12: "\x1b[24~",
80}
81
82// encodeRune encodes a printable character, with the escape prefix that stands
83// for Alt.
84func encodeRune(ev *tcell.EventKey) []byte {
85 text := []byte(string(ev.Rune()))
86 if ev.Modifiers()&tcell.ModAlt != 0 {
87 return append([]byte{escape}, text...)
88 }
89 return text
90}
91
92// encodeControl encodes a Ctrl-key press.
93//
94// tcell does not report the control byte itself: reading 0x03 from the
95// terminal, it posts KeyCtrlSpace+3, and KeyCtrlSpace is 64. So the whole
96// range 64…95 stands for the control bytes 0…31, and turning a key back into
97// what a terminal expects means subtracting that offset again.
98//
99// Getting this wrong is silent: every Ctrl-key would simply send nothing.
100func encodeControl(ev *tcell.EventKey) []byte {
101 key := ev.Key()
102 if key < tcell.KeyCtrlSpace || key > tcell.KeyCtrlUnderscore {
103 return nil
104 }
105
106 control := byte(key - tcell.KeyCtrlSpace)
107 if ev.Modifiers()&tcell.ModAlt != 0 {
108 return []byte{escape, control}
109 }
110 return []byte{control}
111}