or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

commands.mdindex.mdinput.mdprogram.mdscreen.md

input.mddocs/

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

```