or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

colors-styling.mdindex.mdkey-bindings.mdmain-interface.mdpopups.mdwidgets.md

key-bindings.mddocs/

0

# Key Bindings and Events

1

2

Global and widget-specific key binding system for handling user input, navigation, and custom commands in both overview and focus modes.

3

4

## Capabilities

5

6

### Global Key Bindings

7

8

System for binding keys to functions that work in overview mode (when no widget is focused).

9

10

```python { .api }

11

def add_key_command(key: Union[int, List[int]], command: Callable[[], Any]) -> None:

12

"""

13

Add a global key binding for overview mode.

14

15

Parameters:

16

- key: Key code or list of key codes to bind

17

- command: No-argument function to execute when key is pressed

18

"""

19

```

20

21

Usage example:

22

```python

23

import py_cui

24

25

def save_action():

26

print('Save action triggered')

27

28

def quit_action():

29

print('Quitting application')

30

root.stop()

31

32

def help_action():

33

root.show_message_popup('Help', 'F1: Help, S: Save, Q: Quit')

34

35

root = py_cui.PyCUI(3, 3)

36

37

# Single key binding

38

root.add_key_command(py_cui.keys.KEY_S_LOWER, save_action)

39

40

# Multiple keys for same action

41

root.add_key_command([py_cui.keys.KEY_Q_LOWER, py_cui.keys.KEY_ESCAPE], quit_action)

42

43

# Function key binding

44

root.add_key_command(py_cui.keys.KEY_F1, help_action)

45

```

46

47

### Widget Key Bindings

48

49

System for binding keys to functions that work when a specific widget is in focus mode.

50

51

```python { .api }

52

# Widget method for adding key commands

53

def add_key_command(key: Union[int, List[int]], command: Callable[[], Any]) -> None:

54

"""

55

Add a key binding specific to this widget (focus mode).

56

57

Parameters:

58

- key: Key code or list of key codes to bind

59

- command: No-argument function to execute when key is pressed in focus mode

60

"""

61

```

62

63

Usage example:

64

```python

65

import py_cui

66

67

root = py_cui.PyCUI(3, 3)

68

menu = root.add_scroll_menu('Options', 0, 0)

69

text_box = root.add_text_box('Input', 1, 0)

70

71

# Menu-specific key bindings

72

def delete_item():

73

menu.remove_selected_item()

74

75

def clear_menu():

76

menu.clear()

77

78

menu.add_key_command(py_cui.keys.KEY_DELETE, delete_item)

79

menu.add_key_command(py_cui.keys.KEY_CTRL_K, clear_menu)

80

81

# Text box specific key bindings

82

def clear_text():

83

text_box.clear()

84

85

def insert_timestamp():

86

import datetime

87

text_box.write(f' [{datetime.datetime.now()}]')

88

89

text_box.add_key_command(py_cui.keys.KEY_CTRL_L, clear_text)

90

text_box.add_key_command(py_cui.keys.KEY_F5, insert_timestamp)

91

```

92

93

### Widget Navigation Control

94

95

Configuration for navigation keys and widget cycling behavior.

96

97

```python { .api }

98

def set_widget_cycle_key(forward_cycle_key: int = None,

99

reverse_cycle_key: int = None) -> None:

100

"""

101

Set keys for cycling between widgets.

102

103

Parameters:

104

- forward_cycle_key: Key for forward widget cycling (default: Ctrl+Right)

105

- reverse_cycle_key: Key for reverse widget cycling (default: Ctrl+Left)

106

"""

107

```

108

109

Usage example:

110

```python

111

root = py_cui.PyCUI(3, 3)

112

113

# Use Tab/Shift+Tab for widget cycling

114

root.set_widget_cycle_key(

115

forward_cycle_key=py_cui.keys.KEY_TAB,

116

reverse_cycle_key=py_cui.keys.KEY_SHIFT_TAB

117

)

118

119

# Add some widgets to cycle through

120

menu = root.add_scroll_menu('Menu', 0, 0)

121

text_box = root.add_text_box('Input', 0, 1)

122

button = root.add_button('Submit', 0, 2)

123

```

124

125

### Mouse Event Bindings

126

127

System for handling mouse clicks and events on widgets.

128

129

```python { .api }

130

# Widget method for adding mouse commands

131

def add_mouse_command(mouse_event: int, command: Callable[[], Any]) -> None:

132

"""

133

Add a mouse event binding to this widget.

134

135

Parameters:

136

- mouse_event: Mouse event code (button click, double-click, etc.)

137

- command: No-argument function to execute on mouse event

138

"""

139

```

140

141

Usage example:

142

```python

143

import py_cui

144

145

def handle_right_click():

146

root.show_menu_popup('Context Menu', ['Edit', 'Delete', 'Properties'],

147

lambda x: print(f'Selected: {x}'))

148

149

def handle_double_click():

150

print('Double-clicked on menu item')

151

152

root = py_cui.PyCUI(3, 3)

153

menu = root.add_scroll_menu('File List', 0, 0, row_span=2)

154

155

# Add mouse event handlers

156

menu.add_mouse_command(py_cui.keys.MOUSE_RIGHT_CLICK, handle_right_click)

157

menu.add_mouse_command(py_cui.keys.MOUSE_DOUBLE_CLICK, handle_double_click)

158

```

159

160

### Key Constants and Utilities

161

162

Key codes and utilities for working with keyboard input.

163

164

```python { .api }

165

# Common key constants

166

KEY_ENTER: int

167

KEY_ESCAPE: int

168

KEY_TAB: int

169

KEY_BACKSPACE: int

170

KEY_DELETE: int

171

172

# Arrow keys

173

KEY_UP_ARROW: int

174

KEY_DOWN_ARROW: int

175

KEY_LEFT_ARROW: int

176

KEY_RIGHT_ARROW: int

177

ARROW_KEYS: List[int] # List of all arrow key codes

178

179

# Function keys

180

KEY_F1: int

181

KEY_F2: int

182

# ... F3 through F12

183

184

# Control key combinations

185

KEY_CTRL_A: int

186

KEY_CTRL_C: int

187

KEY_CTRL_V: int

188

KEY_CTRL_X: int

189

KEY_CTRL_Z: int

190

# ... other Ctrl combinations

191

192

# Letter keys (upper and lower case)

193

KEY_A_UPPER: int

194

KEY_A_LOWER: int

195

# ... other letters

196

197

# Number keys

198

KEY_0: int

199

KEY_1: int

200

# ... other numbers

201

202

# Special keys

203

KEY_SPACE: int

204

KEY_SHIFT_TAB: int

205

206

# Mouse events

207

MOUSE_LEFT_CLICK: int

208

MOUSE_RIGHT_CLICK: int

209

MOUSE_DOUBLE_CLICK: int

210

211

# Utility functions

212

def get_char_from_ascii(key_code: int) -> Optional[str]:

213

"""

214

Convert key code to character representation.

215

216

Parameters:

217

- key_code: ASCII key code

218

219

Returns:

220

String representation of key or None if not printable

221

"""

222

```

223

224

Usage example:

225

```python

226

import py_cui

227

228

def handle_key_press():

229

# Example of using key constants

230

print('Key pressed!')

231

232

def show_key_help():

233

help_text = f"""

234

Available Keys:

235

{py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_F1)} - Help

236

{py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_S_LOWER)} - Save

237

{py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_Q_LOWER)} - Quit

238

Arrows - Navigate

239

Enter - Select

240

Escape - Cancel

241

"""

242

root.show_message_popup('Key Help', help_text)

243

244

root = py_cui.PyCUI(3, 3)

245

246

# Bind various key types

247

root.add_key_command(py_cui.keys.KEY_F1, show_key_help)

248

root.add_key_command(py_cui.keys.KEY_CTRL_H, show_key_help)

249

root.add_key_command(py_cui.keys.KEY_SPACE, handle_key_press)

250

251

# Check if keys are arrow keys

252

def handle_any_key(key_code: int):

253

if key_code in py_cui.keys.ARROW_KEYS:

254

print('Arrow key pressed')

255

char = py_cui.keys.get_char_from_ascii(key_code)

256

if char:

257

print(f'Printable key: {char}')

258

```

259

260

### Advanced Key Binding Patterns

261

262

Examples of complex key binding scenarios and patterns.

263

264

```python { .api }

265

# Advanced binding patterns (examples)

266

```

267

268

Usage example:

269

```python

270

import py_cui

271

272

class KeyBindingDemo:

273

def __init__(self):

274

self.root = py_cui.PyCUI(3, 3)

275

self.mode = 'normal'

276

277

# Create widgets

278

self.setup_widgets()

279

self.setup_key_bindings()

280

281

def setup_widgets(self):

282

self.menu = self.root.add_scroll_menu('Commands', 0, 0)

283

self.output = self.root.add_text_block('Output', 0, 1, column_span=2)

284

self.input_box = self.root.add_text_box('Input', 1, 0, column_span=3)

285

286

def setup_key_bindings(self):

287

# Modal key bindings - different behavior based on mode

288

self.root.add_key_command(py_cui.keys.KEY_I_LOWER, self.enter_insert_mode)

289

self.root.add_key_command(py_cui.keys.KEY_ESCAPE, self.enter_normal_mode)

290

291

# Conditional key bindings

292

self.root.add_key_command(py_cui.keys.KEY_ENTER, self.context_sensitive_enter)

293

294

# Multi-key sequences (simple implementation)

295

self.last_key = None

296

self.root.add_key_command(py_cui.keys.KEY_G_LOWER, self.handle_g_key)

297

298

def enter_insert_mode(self):

299

self.mode = 'insert'

300

self.root.set_status_bar_text('-- INSERT MODE --')

301

self.root.move_focus(self.input_box)

302

303

def enter_normal_mode(self):

304

self.mode = 'normal'

305

self.root.set_status_bar_text('-- NORMAL MODE --')

306

self.root.lose_focus()

307

308

def context_sensitive_enter(self):

309

if self.mode == 'normal':

310

selected = self.root.get_selected_widget()

311

if selected == self.menu:

312

self.execute_command()

313

elif self.mode == 'insert':

314

self.process_input()

315

316

def handle_g_key(self):

317

# Simple two-key sequence: 'gg' to go to top

318

if self.last_key == py_cui.keys.KEY_G_LOWER:

319

self.goto_top()

320

self.last_key = None

321

else:

322

self.last_key = py_cui.keys.KEY_G_LOWER

323

324

def execute_command(self):

325

command = self.menu.get_selected_item()

326

self.output.write(f'Executing: {command}\n')

327

328

def process_input(self):

329

text = self.input_box.get()

330

self.output.write(f'Input: {text}\n')

331

self.input_box.clear()

332

333

def goto_top(self):

334

self.menu.set_selected_item_index(0)

335

self.output.write('Jumped to top\n')

336

337

def run(self):

338

self.menu.add_item_list(['save', 'load', 'quit', 'help'])

339

self.root.start()

340

341

# Usage

342

demo = KeyBindingDemo()

343

demo.run()

344

```