key.go

  1package tea
  2
  3import (
  4	"fmt"
  5
  6	uv "github.com/charmbracelet/ultraviolet"
  7)
  8
  9const (
 10	// KeyExtended is a special key code used to signify that a key event
 11	// contains multiple runes.
 12	KeyExtended = uv.KeyExtended
 13)
 14
 15// Special key symbols.
 16const (
 17
 18	// Special keys.
 19
 20	KeyUp     = uv.KeyUp
 21	KeyDown   = uv.KeyDown
 22	KeyRight  = uv.KeyRight
 23	KeyLeft   = uv.KeyLeft
 24	KeyBegin  = uv.KeyBegin
 25	KeyFind   = uv.KeyFind
 26	KeyInsert = uv.KeyInsert
 27	KeyDelete = uv.KeyDelete
 28	KeySelect = uv.KeySelect
 29	KeyPgUp   = uv.KeyPgUp
 30	KeyPgDown = uv.KeyPgDown
 31	KeyHome   = uv.KeyHome
 32	KeyEnd    = uv.KeyEnd
 33
 34	// Keypad keys.
 35
 36	KeyKpEnter    = uv.KeyKpEnter
 37	KeyKpEqual    = uv.KeyKpEqual
 38	KeyKpMultiply = uv.KeyKpMultiply
 39	KeyKpPlus     = uv.KeyKpPlus
 40	KeyKpComma    = uv.KeyKpComma
 41	KeyKpMinus    = uv.KeyKpMinus
 42	KeyKpDecimal  = uv.KeyKpDecimal
 43	KeyKpDivide   = uv.KeyKpDivide
 44	KeyKp0        = uv.KeyKp0
 45	KeyKp1        = uv.KeyKp1
 46	KeyKp2        = uv.KeyKp2
 47	KeyKp3        = uv.KeyKp3
 48	KeyKp4        = uv.KeyKp4
 49	KeyKp5        = uv.KeyKp5
 50	KeyKp6        = uv.KeyKp6
 51	KeyKp7        = uv.KeyKp7
 52	KeyKp8        = uv.KeyKp8
 53	KeyKp9        = uv.KeyKp9
 54
 55	// The following are keys defined in the Kitty keyboard protocol.
 56	// XXX: Investigate the names of these keys.
 57	KeyKpSep    = uv.KeyKpSep
 58	KeyKpUp     = uv.KeyKpUp
 59	KeyKpDown   = uv.KeyKpDown
 60	KeyKpLeft   = uv.KeyKpLeft
 61	KeyKpRight  = uv.KeyKpRight
 62	KeyKpPgUp   = uv.KeyKpPgUp
 63	KeyKpPgDown = uv.KeyKpPgDown
 64	KeyKpHome   = uv.KeyKpHome
 65	KeyKpEnd    = uv.KeyKpEnd
 66	KeyKpInsert = uv.KeyKpInsert
 67	KeyKpDelete = uv.KeyKpDelete
 68	KeyKpBegin  = uv.KeyKpBegin
 69
 70	// Function keys.
 71
 72	KeyF1  = uv.KeyF1
 73	KeyF2  = uv.KeyF2
 74	KeyF3  = uv.KeyF3
 75	KeyF4  = uv.KeyF4
 76	KeyF5  = uv.KeyF5
 77	KeyF6  = uv.KeyF6
 78	KeyF7  = uv.KeyF7
 79	KeyF8  = uv.KeyF8
 80	KeyF9  = uv.KeyF9
 81	KeyF10 = uv.KeyF10
 82	KeyF11 = uv.KeyF11
 83	KeyF12 = uv.KeyF12
 84	KeyF13 = uv.KeyF13
 85	KeyF14 = uv.KeyF14
 86	KeyF15 = uv.KeyF15
 87	KeyF16 = uv.KeyF16
 88	KeyF17 = uv.KeyF17
 89	KeyF18 = uv.KeyF18
 90	KeyF19 = uv.KeyF19
 91	KeyF20 = uv.KeyF20
 92	KeyF21 = uv.KeyF21
 93	KeyF22 = uv.KeyF22
 94	KeyF23 = uv.KeyF23
 95	KeyF24 = uv.KeyF24
 96	KeyF25 = uv.KeyF25
 97	KeyF26 = uv.KeyF26
 98	KeyF27 = uv.KeyF27
 99	KeyF28 = uv.KeyF28
100	KeyF29 = uv.KeyF29
101	KeyF30 = uv.KeyF30
102	KeyF31 = uv.KeyF31
103	KeyF32 = uv.KeyF32
104	KeyF33 = uv.KeyF33
105	KeyF34 = uv.KeyF34
106	KeyF35 = uv.KeyF35
107	KeyF36 = uv.KeyF36
108	KeyF37 = uv.KeyF37
109	KeyF38 = uv.KeyF38
110	KeyF39 = uv.KeyF39
111	KeyF40 = uv.KeyF40
112	KeyF41 = uv.KeyF41
113	KeyF42 = uv.KeyF42
114	KeyF43 = uv.KeyF43
115	KeyF44 = uv.KeyF44
116	KeyF45 = uv.KeyF45
117	KeyF46 = uv.KeyF46
118	KeyF47 = uv.KeyF47
119	KeyF48 = uv.KeyF48
120	KeyF49 = uv.KeyF49
121	KeyF50 = uv.KeyF50
122	KeyF51 = uv.KeyF51
123	KeyF52 = uv.KeyF52
124	KeyF53 = uv.KeyF53
125	KeyF54 = uv.KeyF54
126	KeyF55 = uv.KeyF55
127	KeyF56 = uv.KeyF56
128	KeyF57 = uv.KeyF57
129	KeyF58 = uv.KeyF58
130	KeyF59 = uv.KeyF59
131	KeyF60 = uv.KeyF60
132	KeyF61 = uv.KeyF61
133	KeyF62 = uv.KeyF62
134	KeyF63 = uv.KeyF63
135
136	// The following are keys defined in the Kitty keyboard protocol.
137	// XXX: Investigate the names of these keys.
138
139	KeyCapsLock    = uv.KeyCapsLock
140	KeyScrollLock  = uv.KeyScrollLock
141	KeyNumLock     = uv.KeyNumLock
142	KeyPrintScreen = uv.KeyPrintScreen
143	KeyPause       = uv.KeyPause
144	KeyMenu        = uv.KeyMenu
145
146	KeyMediaPlay        = uv.KeyMediaPlay
147	KeyMediaPause       = uv.KeyMediaPause
148	KeyMediaPlayPause   = uv.KeyMediaPlayPause
149	KeyMediaReverse     = uv.KeyMediaReverse
150	KeyMediaStop        = uv.KeyMediaStop
151	KeyMediaFastForward = uv.KeyMediaFastForward
152	KeyMediaRewind      = uv.KeyMediaRewind
153	KeyMediaNext        = uv.KeyMediaNext
154	KeyMediaPrev        = uv.KeyMediaPrev
155	KeyMediaRecord
156
157	KeyLowerVol = uv.KeyLowerVol
158	KeyRaiseVol = uv.KeyRaiseVol
159	KeyMute     = uv.KeyMute
160
161	KeyLeftShift      = uv.KeyLeftShift
162	KeyLeftAlt        = uv.KeyLeftAlt
163	KeyLeftCtrl       = uv.KeyLeftCtrl
164	KeyLeftSuper      = uv.KeyLeftSuper
165	KeyLeftHyper      = uv.KeyLeftHyper
166	KeyLeftMeta       = uv.KeyLeftMeta
167	KeyRightShift     = uv.KeyRightShift
168	KeyRightAlt       = uv.KeyRightAlt
169	KeyRightCtrl      = uv.KeyRightCtrl
170	KeyRightSuper     = uv.KeyRightSuper
171	KeyRightHyper     = uv.KeyRightHyper
172	KeyRightMeta      = uv.KeyRightMeta
173	KeyIsoLevel3Shift = uv.KeyIsoLevel3Shift
174	KeyIsoLevel5Shift = uv.KeyIsoLevel5Shift
175
176	// Special names in C0.
177
178	KeyBackspace = uv.KeyBackspace
179	KeyTab       = uv.KeyTab
180	KeyEnter     = uv.KeyEnter
181	KeyReturn    = uv.KeyReturn
182	KeyEscape    = uv.KeyEscape
183	KeyEsc       = uv.KeyEsc
184
185	// Special names in G0.
186
187	KeySpace = uv.KeySpace
188)
189
190// KeyPressMsg represents a key press message.
191type KeyPressMsg Key
192
193// String implements [fmt.Stringer] and is quite useful for matching key
194// events. For details, on what this returns see [Key.String].
195func (k KeyPressMsg) String() string {
196	return Key(k).String()
197}
198
199// Keystroke returns the keystroke representation of the [Key]. While less type
200// safe than looking at the individual fields, it will usually be more
201// convenient and readable to use this method when matching against keys.
202//
203// Note that modifier keys are always printed in the following order:
204//   - ctrl
205//   - alt
206//   - shift
207//   - meta
208//   - hyper
209//   - super
210//
211// For example, you'll always see "ctrl+shift+alt+a" and never
212// "shift+ctrl+alt+a".
213func (k KeyPressMsg) Keystroke() string {
214	return uv.Key(k).Keystroke()
215}
216
217// Key returns the underlying key event. This is a syntactic sugar for casting
218// the key event to a [Key].
219func (k KeyPressMsg) Key() Key {
220	return Key(k)
221}
222
223// KeyReleaseMsg represents a key release message.
224type KeyReleaseMsg Key
225
226// String implements [fmt.Stringer] and is quite useful for matching key
227// events. For details, on what this returns see [Key.String].
228func (k KeyReleaseMsg) String() string {
229	return Key(k).String()
230}
231
232// Keystroke returns the keystroke representation of the [Key]. While less type
233// safe than looking at the individual fields, it will usually be more
234// convenient and readable to use this method when matching against keys.
235//
236// Note that modifier keys are always printed in the following order:
237//   - ctrl
238//   - alt
239//   - shift
240//   - meta
241//   - hyper
242//   - super
243//
244// For example, you'll always see "ctrl+shift+alt+a" and never
245// "shift+ctrl+alt+a".
246func (k KeyReleaseMsg) Keystroke() string {
247	return uv.Key(k).Keystroke()
248}
249
250// Key returns the underlying key event. This is a convenience method and
251// syntactic sugar to satisfy the [KeyMsg] interface, and cast the key event to
252// [Key].
253func (k KeyReleaseMsg) Key() Key {
254	return Key(k)
255}
256
257// KeyMsg represents a key event. This can be either a key press or a key
258// release event.
259type KeyMsg interface {
260	fmt.Stringer
261
262	// Key returns the underlying key event.
263	Key() Key
264}
265
266// Key represents a Key press or release event. It contains information about
267// the Key pressed, like the runes, the type of Key, and the modifiers pressed.
268// There are a couple general patterns you could use to check for key presses
269// or releases:
270//
271//	// Switch on the string representation of the key (shorter)
272//	switch msg := msg.(type) {
273//	case KeyPressMsg:
274//	    switch msg.String() {
275//	    case "enter":
276//	        fmt.Println("you pressed enter!")
277//	    case "a":
278//	        fmt.Println("you pressed a!")
279//	    }
280//	}
281//
282//	// Switch on the key type (more foolproof)
283//	switch msg := msg.(type) {
284//	case KeyMsg:
285//	    // catch both KeyPressMsg and KeyReleaseMsg
286//	    switch key := msg.Key(); key.Code {
287//	    case KeyEnter:
288//	        fmt.Println("you pressed enter!")
289//	    default:
290//	        switch key.Text {
291//	        case "a":
292//	            fmt.Println("you pressed a!")
293//	        }
294//	    }
295//	}
296//
297// Note that [Key.Text] will be empty for special keys like [KeyEnter],
298// [KeyTab], and for keys that don't represent printable characters like key
299// combos with modifier keys. In other words, [Key.Text] is populated only for
300// keys that represent printable characters shifted or unshifted (like 'a',
301// 'A', '1', '!', etc.).
302type Key struct {
303	// Text contains the actual characters received. This usually the same as
304	// [Key.Code]. When [Key.Text] is non-empty, it indicates that the key
305	// pressed represents printable character(s).
306	Text string
307
308	// Mod represents modifier keys, like [ModCtrl], [ModAlt], and so on.
309	Mod KeyMod
310
311	// Code represents the key pressed. This is usually a special key like
312	// [KeyTab], [KeyEnter], [KeyF1], or a printable character like 'a'.
313	Code rune
314
315	// ShiftedCode is the actual, shifted key pressed by the user. For example,
316	// if the user presses shift+a, or caps lock is on, [Key.ShiftedCode] will
317	// be 'A' and [Key.Code] will be 'a'.
318	//
319	// In the case of non-latin keyboards, like Arabic, [Key.ShiftedCode] is the
320	// unshifted key on the keyboard.
321	//
322	// This is only available with the Kitty Keyboard Protocol or the Windows
323	// Console API.
324	ShiftedCode rune
325
326	// BaseCode is the key pressed according to the standard PC-101 key layout.
327	// On international keyboards, this is the key that would be pressed if the
328	// keyboard was set to US PC-101 layout.
329	//
330	// For example, if the user presses 'q' on a French AZERTY keyboard,
331	// [Key.BaseCode] will be 'q'.
332	//
333	// This is only available with the Kitty Keyboard Protocol or the Windows
334	// Console API.
335	BaseCode rune
336
337	// IsRepeat indicates whether the key is being held down and sending events
338	// repeatedly.
339	//
340	// This is only available with the Kitty Keyboard Protocol or the Windows
341	// Console API.
342	IsRepeat bool
343}
344
345// String implements [fmt.Stringer] and is quite useful for matching key
346// events. It will return the textual representation of the [Key] if there is
347// one, otherwise, it will fallback to [Key.Keystroke].
348//
349// For example, you'll always get "?" and instead of "shift+/" on a US ANSI
350// keyboard.
351func (k Key) String() string {
352	return uv.Key(k).String()
353}
354
355// Keystroke returns the keystroke representation of the [Key]. While less type
356// safe than looking at the individual fields, it will usually be more
357// convenient and readable to use this method when matching against keys.
358//
359// Note that modifier keys are always printed in the following order:
360//   - ctrl
361//   - alt
362//   - shift
363//   - meta
364//   - hyper
365//   - super
366//
367// For example, you'll always see "ctrl+shift+alt+a" and never
368// "shift+ctrl+alt+a".
369func (k Key) Keystroke() string {
370	return uv.Key(k).Keystroke()
371}