0
# Terminal Control
1
2
Complete terminal and screen control functionality including alternate screen buffer, mouse modes, cursor control, focus reporting, and bracketed paste mode.
3
4
## Capabilities
5
6
### Screen Buffer Management
7
8
Control alternate screen buffer for full-screen terminal applications.
9
10
```go { .api }
11
/**
12
* ClearScreen clears the screen before next update
13
* Moves cursor to top-left and clears visual clutter
14
* Only needed for special cases, not regular redraws
15
* @returns Message to clear screen
16
*/
17
func ClearScreen() Msg
18
19
/**
20
* EnterAltScreen switches to alternate screen buffer
21
* Provides full-window mode, hiding terminal history
22
* Screen automatically restored on program exit
23
* @returns Message to enter alternate screen
24
*/
25
func EnterAltScreen() Msg
26
27
/**
28
* ExitAltScreen switches back to main screen buffer
29
* Returns to normal terminal with history visible
30
* Usually not needed as altscreen auto-exits on quit
31
* @returns Message to exit alternate screen
32
*/
33
func ExitAltScreen() Msg
34
```
35
36
**Usage Examples:**
37
38
```go
39
// Initialize with alternate screen
40
p := tea.NewProgram(model{}, tea.WithAltScreen())
41
42
// Or use commands for dynamic control
43
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
44
switch msg := msg.(type) {
45
case tea.KeyMsg:
46
switch msg.String() {
47
case "f":
48
return m, tea.EnterAltScreen()
49
case "ctrl+z":
50
// Clear screen before suspending
51
return m, tea.Batch(
52
tea.ClearScreen(),
53
tea.Suspend(),
54
)
55
}
56
}
57
return m, nil
58
}
59
```
60
61
### Mouse Control
62
63
Enable and configure mouse input modes.
64
65
```go { .api }
66
/**
67
* EnableMouseCellMotion enables mouse click, release, and wheel events
68
* Also captures mouse movement when button is pressed (drag events)
69
* Better terminal compatibility than all motion mode
70
* @returns Message to enable cell motion mouse mode
71
*/
72
func EnableMouseCellMotion() Msg
73
74
/**
75
* EnableMouseAllMotion enables all mouse events including hover
76
* Captures click, release, wheel, and motion without button press
77
* Less widely supported, use cell motion if unsure
78
* @returns Message to enable all motion mouse mode
79
*/
80
func EnableMouseAllMotion() Msg
81
82
/**
83
* DisableMouse stops listening for mouse events
84
* Mouse automatically disabled when program exits
85
* @returns Message to disable mouse input
86
*/
87
func DisableMouse() Msg
88
```
89
90
**Usage Examples:**
91
92
```go
93
// Static configuration (recommended)
94
p := tea.NewProgram(model{},
95
tea.WithMouseCellMotion(), // or WithMouseAllMotion()
96
)
97
98
// Dynamic mouse control
99
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
100
switch msg := msg.(type) {
101
case tea.KeyMsg:
102
switch msg.String() {
103
case "m":
104
if m.mouseEnabled {
105
m.mouseEnabled = false
106
return m, tea.DisableMouse()
107
} else {
108
m.mouseEnabled = true
109
return m, tea.EnableMouseCellMotion()
110
}
111
}
112
case tea.MouseMsg:
113
// Handle mouse events
114
return m.handleMouse(msg), nil
115
}
116
return m, nil
117
}
118
```
119
120
### Cursor Control
121
122
Show and hide the terminal cursor.
123
124
```go { .api }
125
/**
126
* HideCursor hides the terminal cursor
127
* Cursor automatically hidden during normal program lifetime
128
* Rarely needed unless terminal operations show cursor unexpectedly
129
* @returns Message to hide cursor
130
*/
131
func HideCursor() Msg
132
133
/**
134
* ShowCursor shows the terminal cursor
135
* Useful for input fields or when cursor should be visible
136
* @returns Message to show cursor
137
*/
138
func ShowCursor() Msg
139
```
140
141
**Usage Examples:**
142
143
```go
144
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
145
switch msg := msg.(type) {
146
case tea.KeyMsg:
147
switch msg.String() {
148
case "i":
149
// Enter input mode, show cursor
150
m.inputMode = true
151
return m, tea.ShowCursor()
152
case "esc":
153
// Exit input mode, hide cursor
154
m.inputMode = false
155
return m, tea.HideCursor()
156
}
157
}
158
return m, nil
159
}
160
```
161
162
### Bracketed Paste Control
163
164
Manage bracketed paste mode for handling large clipboard content.
165
166
```go { .api }
167
/**
168
* EnableBracketedPaste enables bracketed paste mode
169
* Large pastes delivered as single KeyMsg with Paste=true
170
* Bracketed paste enabled by default unless disabled via option
171
* @returns Message to enable bracketed paste
172
*/
173
func EnableBracketedPaste() Msg
174
175
/**
176
* DisableBracketedPaste disables bracketed paste mode
177
* Each character in paste delivered as separate KeyMsg
178
* @returns Message to disable bracketed paste
179
*/
180
func DisableBracketedPaste() Msg
181
```
182
183
**Usage Examples:**
184
185
```go
186
// Disable via program option
187
p := tea.NewProgram(model{}, tea.WithoutBracketedPaste())
188
189
// Dynamic control
190
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
191
switch msg := msg.(type) {
192
case tea.KeyMsg:
193
if msg.Paste {
194
// Handle large paste operation
195
m.content += string(msg.Runes)
196
return m, nil
197
}
198
// Handle regular keystrokes
199
return m.handleKey(msg), nil
200
}
201
return m, nil
202
}
203
```
204
205
### Focus Reporting
206
207
Enable terminal focus and blur event reporting.
208
209
```go { .api }
210
/**
211
* EnableReportFocus enables focus/blur event reporting
212
* Sends FocusMsg when terminal gains focus
213
* Sends BlurMsg when terminal loses focus
214
* @returns Message to enable focus reporting
215
*/
216
func EnableReportFocus() Msg
217
218
/**
219
* DisableReportFocus disables focus/blur event reporting
220
* @returns Message to disable focus reporting
221
*/
222
func DisableReportFocus() Msg
223
```
224
225
**Usage Examples:**
226
227
```go
228
// Enable via program option
229
p := tea.NewProgram(model{}, tea.WithReportFocus())
230
231
// Handle focus events
232
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
233
switch msg.(type) {
234
case tea.FocusMsg:
235
m.focused = true
236
// Maybe pause animations when not focused
237
return m, m.startAnimationCmd()
238
case tea.BlurMsg:
239
m.focused = false
240
// Pause updates when not focused
241
return m, nil
242
}
243
return m, nil
244
}
245
```
246
247
### Window Size Information
248
249
Handle terminal resize events and query current dimensions.
250
251
```go { .api }
252
/**
253
* WindowSizeMsg reports current terminal dimensions
254
* Automatically sent on program start and terminal resize
255
* Width and height in character cells (not pixels)
256
*/
257
type WindowSizeMsg struct {
258
Width int // Terminal width in characters
259
Height int // Terminal height in characters
260
}
261
```
262
263
**Usage Examples:**
264
265
```go
266
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
267
switch msg := msg.(type) {
268
case tea.WindowSizeMsg:
269
m.width = msg.Width
270
m.height = msg.Height
271
272
// Adjust layout based on size
273
if msg.Width < 80 {
274
m.layout = "compact"
275
} else {
276
m.layout = "full"
277
}
278
279
return m, nil
280
}
281
return m, nil
282
}
283
284
func (m model) View() string {
285
// Use m.width and m.height for responsive layout
286
content := m.renderContent()
287
288
// Ensure content fits terminal
289
if len(content) > m.height-1 {
290
content = content[:m.height-1]
291
}
292
293
return strings.Join(content, "\n")
294
}
295
```
296
297
## Deprecated Program Methods
298
299
These methods exist for backwards compatibility but should be avoided:
300
301
```go { .api }
302
/**
303
* Deprecated: Use WithAltScreen program option instead
304
* EnterAltScreen enters alternate screen if renderer is available
305
*/
306
func (p *Program) EnterAltScreen()
307
308
/**
309
* Deprecated: Altscreen automatically exits when program ends
310
* ExitAltScreen exits alternate screen if renderer is available
311
*/
312
func (p *Program) ExitAltScreen()
313
314
/**
315
* Deprecated: Use WithMouseCellMotion program option instead
316
* EnableMouseCellMotion enables mouse cell motion
317
*/
318
func (p *Program) EnableMouseCellMotion()
319
320
/**
321
* Deprecated: Mouse automatically disabled on program exit
322
* DisableMouseCellMotion disables mouse cell motion
323
*/
324
func (p *Program) DisableMouseCellMotion()
325
326
/**
327
* Deprecated: Use WithMouseAllMotion program option instead
328
* EnableMouseAllMotion enables mouse all motion
329
*/
330
func (p *Program) EnableMouseAllMotion()
331
332
/**
333
* Deprecated: Mouse automatically disabled on program exit
334
* DisableMouseAllMotion disables mouse all motion
335
*/
336
func (p *Program) DisableMouseAllMotion()
337
338
/**
339
* Deprecated: Use SetWindowTitle command instead
340
* SetWindowTitle sets window title if renderer is available
341
*/
342
func (p *Program) SetWindowTitle(title string)
343
```
344
345
## Terminal State Management Patterns
346
347
### Responsive Layout
348
349
Pattern for handling different terminal sizes:
350
351
```go
352
type layout struct {
353
compact bool
354
columns int
355
rows int
356
}
357
358
func (l layout) maxContentWidth() int {
359
if l.compact {
360
return l.columns - 2 // Leave margins
361
}
362
return min(l.columns-4, 120) // Max width for readability
363
}
364
365
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
366
switch msg := msg.(type) {
367
case tea.WindowSizeMsg:
368
m.layout = layout{
369
compact: msg.Width < 80,
370
columns: msg.Width,
371
rows: msg.Height,
372
}
373
return m, nil
374
}
375
return m, nil
376
}
377
378
func (m model) View() string {
379
maxWidth := m.layout.maxContentWidth()
380
content := wrapText(m.content, maxWidth)
381
382
if m.layout.compact {
383
return m.renderCompactView(content)
384
}
385
return m.renderFullView(content)
386
}
387
```
388
389
### Focus-Aware Updates
390
391
Pattern for pausing updates when terminal loses focus:
392
393
```go
394
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
395
switch msg.(type) {
396
case tea.FocusMsg:
397
m.focused = true
398
// Resume periodic updates
399
return m, m.startPeriodicUpdate()
400
401
case tea.BlurMsg:
402
m.focused = false
403
// Don't schedule more updates
404
return m, nil
405
406
case tickMsg:
407
if !m.focused {
408
// Skip update if not focused
409
return m, nil
410
}
411
// Normal update and reschedule
412
m.lastUpdate = time.Now()
413
return m, m.startPeriodicUpdate()
414
}
415
return m, nil
416
}
417
```
418
419
### Progressive Feature Detection
420
421
Pattern for enabling features based on terminal capabilities:
422
423
```go
424
func (m model) Init() tea.Cmd {
425
return tea.Batch(
426
tea.WindowSize(), // Get initial size
427
m.detectCapabilitiesCmd(),
428
)
429
}
430
431
type capabilitiesMsg struct {
432
hasMouseSupport bool
433
hasFocusReporting bool
434
hasAltScreen bool
435
}
436
437
func (m model) detectCapabilitiesCmd() tea.Cmd {
438
return func() tea.Msg {
439
// Simple capability detection
440
term := os.Getenv("TERM")
441
442
return capabilitiesMsg{
443
hasMouseSupport: term != "dumb",
444
hasFocusReporting: strings.Contains(term, "xterm"),
445
hasAltScreen: term != "dumb",
446
}
447
}
448
}
449
450
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
451
switch msg := msg.(type) {
452
case capabilitiesMsg:
453
var cmds []tea.Cmd
454
455
if msg.hasMouseSupport {
456
cmds = append(cmds, tea.EnableMouseCellMotion())
457
}
458
if msg.hasFocusReporting {
459
cmds = append(cmds, tea.EnableReportFocus())
460
}
461
if msg.hasAltScreen && m.wantsFullScreen {
462
cmds = append(cmds, tea.EnterAltScreen())
463
}
464
465
return m, tea.Batch(cmds...)
466
}
467
return m, nil
468
}
469
```