0
# Input Handling
1
2
Comprehensive keyboard and mouse input handling system providing support for all standard terminal input including function keys, mouse events, focus events, and bracketed paste mode.
3
4
## Capabilities
5
6
### Keyboard Input
7
8
Keyboard input is delivered through KeyMsg messages containing detailed key information.
9
10
```go { .api }
11
/**
12
* KeyMsg contains information about a keypress
13
* Always sent to the program's update function for keyboard events
14
*/
15
type KeyMsg Key
16
17
type Key struct {
18
Type KeyType // Key type (special keys, control keys, or runes)
19
Runes []rune // Character data (always contains at least one rune for KeyRunes)
20
Alt bool // Alt/Option modifier key pressed
21
Paste bool // Key event originated from bracketed paste
22
}
23
24
/**
25
* Returns friendly string representation of key
26
* Safe and encouraged for key comparison in switch statements
27
*/
28
func (k Key) String() string
29
func (k KeyMsg) String() string
30
```
31
32
**Usage Example:**
33
34
```go
35
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
36
switch msg := msg.(type) {
37
case tea.KeyMsg:
38
// Method 1: String comparison (simpler)
39
switch msg.String() {
40
case "ctrl+c", "q":
41
return m, tea.Quit()
42
case "enter":
43
return m.handleEnter(), nil
44
case "a":
45
return m.addItem(), nil
46
}
47
48
// Method 2: Type-based matching (more robust)
49
switch msg.Type {
50
case tea.KeyEnter:
51
return m.handleEnter(), nil
52
case tea.KeyRunes:
53
switch string(msg.Runes) {
54
case "a":
55
return m.addItem(), nil
56
}
57
}
58
}
59
return m, nil
60
}
61
```
62
63
### Key Types and Constants
64
65
```go { .api }
66
type KeyType int
67
68
// Control key constants
69
const (
70
KeyNull KeyType // null character
71
KeyBreak KeyType // ctrl+c
72
KeyEnter KeyType // enter/return
73
KeyBackspace KeyType // backspace
74
KeyTab KeyType // tab
75
KeyEsc KeyType // escape
76
KeyEscape KeyType // escape (alias)
77
)
78
79
// Ctrl+Letter combinations
80
const (
81
KeyCtrlA KeyType // ctrl+a through ctrl+z
82
KeyCtrlB KeyType
83
// ... (all ctrl+letter combinations available)
84
KeyCtrlZ KeyType
85
)
86
87
// Navigation and special keys
88
const (
89
KeyRunes KeyType // Regular character input
90
KeyUp KeyType // Arrow keys
91
KeyDown KeyType
92
KeyRight KeyType
93
KeyLeft KeyType
94
KeyShiftTab KeyType // Shift+tab
95
KeyHome KeyType // Home/end keys
96
KeyEnd KeyType
97
KeyPgUp KeyType // Page up/down
98
KeyPgDown KeyType
99
KeyDelete KeyType // Delete/insert
100
KeyInsert KeyType
101
KeySpace KeyType // Space bar
102
)
103
104
// Function keys
105
const (
106
KeyF1 KeyType // Function keys F1-F20
107
KeyF2 KeyType
108
KeyF3 KeyType
109
KeyF4 KeyType
110
KeyF5 KeyType
111
KeyF6 KeyType
112
KeyF7 KeyType
113
KeyF8 KeyType
114
KeyF9 KeyType
115
KeyF10 KeyType
116
KeyF11 KeyType
117
KeyF12 KeyType
118
KeyF13 KeyType // Extended function keys (F13-F20)
119
KeyF14 KeyType
120
KeyF15 KeyType
121
KeyF16 KeyType
122
KeyF17 KeyType
123
KeyF18 KeyType
124
KeyF19 KeyType
125
KeyF20 KeyType
126
)
127
128
// Modified navigation keys
129
const (
130
KeyCtrlUp KeyType // Ctrl+arrow combinations
131
KeyCtrlDown KeyType
132
KeyCtrlLeft KeyType
133
KeyCtrlRight KeyType
134
KeyCtrlPgUp KeyType // Ctrl+page up/down
135
KeyCtrlPgDown KeyType
136
KeyShiftUp KeyType // Shift+arrow combinations
137
KeyShiftDown KeyType
138
KeyShiftLeft KeyType
139
KeyShiftRight KeyType
140
KeyCtrlShiftUp KeyType // Ctrl+Shift+arrow combinations
141
KeyCtrlShiftDown KeyType
142
KeyCtrlShiftLeft KeyType
143
KeyCtrlShiftRight KeyType
144
KeyCtrlShiftHome KeyType // Ctrl+Shift+home/end
145
KeyCtrlShiftEnd KeyType
146
)
147
```
148
149
### Mouse Input
150
151
Mouse events are delivered through MouseMsg messages with position and button information.
152
153
```go { .api }
154
/**
155
* MouseMsg contains information about a mouse event
156
* Sent when mouse activity occurs (must be enabled first)
157
*/
158
type MouseMsg MouseEvent
159
160
type MouseEvent struct {
161
X int // Mouse coordinates (0-based)
162
Y int
163
Shift bool // Modifier keys pressed during event
164
Alt bool
165
Ctrl bool
166
Action MouseAction // Type of mouse action
167
Button MouseButton // Which button was involved
168
}
169
170
/**
171
* Checks if the mouse event is a wheel event
172
*/
173
func (m MouseEvent) IsWheel() bool
174
175
/**
176
* Returns string representation of mouse event
177
*/
178
func (m MouseEvent) String() string
179
func (m MouseMsg) String() string
180
```
181
182
**Usage Example:**
183
184
```go
185
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
186
switch msg := msg.(type) {
187
case tea.MouseMsg:
188
switch msg.Action {
189
case tea.MouseActionPress:
190
if msg.Button == tea.MouseButtonLeft {
191
return m.handleClick(msg.X, msg.Y), nil
192
}
193
case tea.MouseActionRelease:
194
return m.handleRelease(), nil
195
case tea.MouseActionMotion:
196
if msg.Button == tea.MouseButtonLeft {
197
return m.handleDrag(msg.X, msg.Y), nil
198
}
199
}
200
201
// Handle wheel events
202
if msg.IsWheel() {
203
switch msg.Button {
204
case tea.MouseButtonWheelUp:
205
return m.scrollUp(), nil
206
case tea.MouseButtonWheelDown:
207
return m.scrollDown(), nil
208
}
209
}
210
}
211
return m, nil
212
}
213
```
214
215
### Mouse Actions and Buttons
216
217
```go { .api }
218
type MouseAction int
219
220
const (
221
MouseActionPress MouseAction // Mouse button pressed
222
MouseActionRelease MouseAction // Mouse button released
223
MouseActionMotion MouseAction // Mouse moved
224
)
225
226
type MouseButton int
227
228
const (
229
MouseButtonNone MouseButton // No button (motion/release events)
230
MouseButtonLeft MouseButton // Left mouse button
231
MouseButtonMiddle MouseButton // Middle button (scroll wheel click)
232
MouseButtonRight MouseButton // Right mouse button
233
MouseButtonWheelUp MouseButton // Scroll wheel up
234
MouseButtonWheelDown MouseButton // Scroll wheel down
235
MouseButtonWheelLeft MouseButton // Scroll wheel left (horizontal)
236
MouseButtonWheelRight MouseButton // Scroll wheel right (horizontal)
237
MouseButtonBackward MouseButton // Browser backward button
238
MouseButtonForward MouseButton // Browser forward button
239
MouseButton10 MouseButton // Additional mouse buttons
240
MouseButton11 MouseButton
241
)
242
```
243
244
### Focus Events
245
246
Terminal focus and blur events when focus reporting is enabled.
247
248
```go { .api }
249
/**
250
* FocusMsg sent when terminal gains focus
251
* Requires WithReportFocus() program option
252
*/
253
type FocusMsg struct{}
254
255
/**
256
* BlurMsg sent when terminal loses focus
257
* Requires WithReportFocus() program option
258
*/
259
type BlurMsg struct{}
260
```
261
262
**Usage Example:**
263
264
```go
265
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
266
switch msg.(type) {
267
case tea.FocusMsg:
268
m.focused = true
269
return m, nil
270
case tea.BlurMsg:
271
m.focused = false
272
return m, nil
273
}
274
return m, nil
275
}
276
277
// Enable focus reporting
278
p := tea.NewProgram(model{}, tea.WithReportFocus())
279
```
280
281
### Window Size Events
282
283
Window resize events are automatically sent when terminal size changes.
284
285
```go { .api }
286
/**
287
* WindowSizeMsg reports terminal dimensions
288
* Sent automatically on program start and when terminal is resized
289
*/
290
type WindowSizeMsg struct {
291
Width int // Terminal width in characters
292
Height int // Terminal height in characters
293
}
294
```
295
296
**Usage Example:**
297
298
```go
299
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
300
switch msg := msg.(type) {
301
case tea.WindowSizeMsg:
302
m.width = msg.Width
303
m.height = msg.Height
304
return m, nil
305
}
306
return m, nil
307
}
308
```
309
310
## Input Mode Configuration
311
312
### Enabling Mouse Input
313
314
Mouse input must be explicitly enabled through program options or commands.
315
316
```go { .api }
317
// Program options (recommended)
318
func WithMouseCellMotion() ProgramOption // Clicks, releases, wheel, drag events
319
func WithMouseAllMotion() ProgramOption // All motion including hover (not all terminals)
320
321
// Runtime commands (for dynamic control)
322
func EnableMouseCellMotion() Msg
323
func EnableMouseAllMotion() Msg
324
func DisableMouse() Msg
325
```
326
327
**Cell Motion vs All Motion:**
328
329
```go
330
// Cell motion: Better supported, captures drag events
331
p := tea.NewProgram(model{}, tea.WithMouseCellMotion())
332
333
// All motion: Includes hover, less widely supported
334
p := tea.NewProgram(model{}, tea.WithMouseAllMotion())
335
336
// Runtime control
337
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
338
switch msg := msg.(type) {
339
case tea.KeyMsg:
340
switch msg.String() {
341
case "m":
342
return m, tea.EnableMouseCellMotion()
343
case "M":
344
return m, tea.DisableMouse()
345
}
346
}
347
return m, nil
348
}
349
```
350
351
### Bracketed Paste Mode
352
353
Handles large clipboard pastes without triggering individual key events.
354
355
```go { .api }
356
// Bracketed paste is enabled by default, disable with:
357
func WithoutBracketedPaste() ProgramOption
358
359
// Runtime control
360
func EnableBracketedPaste() Msg
361
func DisableBracketedPaste() Msg
362
```
363
364
When bracketed paste is enabled, pasted content is marked with the `Paste` field:
365
366
```go
367
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
368
switch msg := msg.(type) {
369
case tea.KeyMsg:
370
if msg.Paste {
371
// Handle pasted content
372
return m.handlePaste(string(msg.Runes)), nil
373
}
374
// Handle regular keystrokes
375
return m.handleKey(msg), nil
376
}
377
return m, nil
378
}
379
```
380
381
### Focus Reporting
382
383
Enable terminal focus/blur event reporting.
384
385
```go { .api }
386
// Program option (recommended)
387
func WithReportFocus() ProgramOption
388
389
// Runtime commands
390
func EnableReportFocus() Msg
391
func DisableReportFocus() Msg
392
```
393
394
## Input Processing Patterns
395
396
### Key Binding Systems
397
398
Common pattern for handling key bindings:
399
400
```go
401
type KeyBindings struct {
402
Up []string
403
Down []string
404
Select []string
405
Quit []string
406
}
407
408
func (kb KeyBindings) Matches(msg tea.KeyMsg, action string) bool {
409
var keys []string
410
switch action {
411
case "up":
412
keys = kb.Up
413
case "down":
414
keys = kb.Down
415
// ... other actions
416
}
417
418
for _, key := range keys {
419
if msg.String() == key {
420
return true
421
}
422
}
423
return false
424
}
425
426
// Usage
427
bindings := KeyBindings{
428
Up: []string{"up", "k"},
429
Down: []string{"down", "j"},
430
Select: []string{"enter", "space"},
431
Quit: []string{"q", "ctrl+c", "esc"},
432
}
433
434
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
435
switch msg := msg.(type) {
436
case tea.KeyMsg:
437
switch {
438
case bindings.Matches(msg, "up"):
439
return m.moveUp(), nil
440
case bindings.Matches(msg, "down"):
441
return m.moveDown(), nil
442
case bindings.Matches(msg, "quit"):
443
return m, tea.Quit()
444
}
445
}
446
return m, nil
447
}
448
```
449
450
### Mouse Hit Testing
451
452
Pattern for handling mouse clicks on UI elements:
453
454
```go
455
type Button struct {
456
Text string
457
X, Y int
458
W, H int
459
}
460
461
func (b Button) Contains(x, y int) bool {
462
return x >= b.X && x < b.X+b.W && y >= b.Y && y < b.Y+b.H
463
}
464
465
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
466
switch msg := msg.(type) {
467
case tea.MouseMsg:
468
if msg.Action == tea.MouseActionPress {
469
for i, button := range m.buttons {
470
if button.Contains(msg.X, msg.Y) {
471
return m.handleButtonClick(i), nil
472
}
473
}
474
}
475
}
476
return m, nil
477
}
478
```