or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

hotkeys.mdindex.mdinteractive-input.mdkey-simulation.mdkeyboard-events.mdrecording-playback.mdtext-processing.md

key-simulation.mddocs/

0

# Key Simulation and Text Input

1

2

Programmatic keyboard input simulation for automating key presses, complex hotkey sequences, and text typing with full unicode support. The keyboard package provides precise control over timing, modifier states, and platform-specific character input methods.

3

4

## Capabilities

5

6

### Basic Key Simulation

7

8

Send individual keys or complex hotkey combinations programmatically.

9

10

```python { .api }

11

def send(hotkey, do_press=True, do_release=True):

12

"""

13

Sends OS events that perform the given hotkey.

14

15

Parameters:

16

- hotkey: Key name, scan code, or multi-key combination (e.g. 'ctrl+alt+del')

17

- do_press: If True, send press events (default: True)

18

- do_release: If True, send release events (default: True)

19

20

Examples:

21

- send('space')

22

- send('ctrl+c')

23

- send('alt+F4, enter') # Multi-step sequence

24

"""

25

26

def press_and_release(hotkey, do_press=True, do_release=True):

27

"""Alias for send(). Sends complete press and release cycle."""

28

29

def press(hotkey):

30

"""

31

Presses and holds down a hotkey (see send).

32

33

Parameters:

34

- hotkey: Key or key combination to press

35

"""

36

37

def release(hotkey):

38

"""

39

Releases a hotkey (see send).

40

41

Parameters:

42

- hotkey: Key or key combination to release

43

"""

44

```

45

46

### Key State Detection

47

48

Check the current state of keys and detect pressed key combinations.

49

50

```python { .api }

51

def is_pressed(hotkey):

52

"""

53

Returns True if the key is pressed.

54

55

Parameters:

56

- hotkey: Key name, scan code, or combination to check

57

58

Returns:

59

bool: True if currently pressed

60

61

Examples:

62

- is_pressed('space') # Single key

63

- is_pressed('ctrl+c') # Key combination

64

"""

65

```

66

67

### Text Input and Unicode Support

68

69

Type text with comprehensive unicode support and keyboard layout awareness.

70

71

```python { .api }

72

def write(text, delay=0, restore_state_after=True, exact=None):

73

"""

74

Sends artificial keyboard events to type the given text. Characters not

75

available on the keyboard are typed as explicit unicode characters using

76

OS-specific functionality.

77

78

Parameters:

79

- text: Text string to type

80

- delay: Seconds to wait between keypresses (default: 0)

81

- restore_state_after: Restore pressed keys after typing (default: True)

82

- exact: Force unicode typing for all characters (default: platform-dependent)

83

84

Notes:

85

- All currently pressed keys are released before typing

86

- Modifier keys are restored after typing if restore_state_after=True

87

- Uses platform-specific unicode input methods for special characters

88

"""

89

```

90

91

### Key State Management

92

93

Advanced state management for complex automation scenarios.

94

95

```python { .api }

96

def stash_state():

97

"""

98

Builds a list of all currently pressed scan codes, releases them and returns

99

the list. Pairs well with restore_state() and restore_modifiers().

100

101

Returns:

102

list: Currently pressed scan codes

103

"""

104

105

def restore_state(scan_codes):

106

"""

107

Given a list of scan codes ensures these keys, and only these keys, are

108

pressed. Pairs well with stash_state().

109

110

Parameters:

111

- scan_codes: List of scan codes to press

112

"""

113

114

def restore_modifiers(scan_codes):

115

"""

116

Like restore_state(), but only restores modifier keys.

117

118

Parameters:

119

- scan_codes: List of scan codes to check for modifiers

120

"""

121

```

122

123

### Key Remapping

124

125

Remap keys to different functions or key combinations.

126

127

```python { .api }

128

def remap_key(src, dst):

129

"""

130

Whenever the key src is pressed or released, regardless of modifiers,

131

press or release the hotkey dst instead.

132

133

Parameters:

134

- src: Source key to remap

135

- dst: Destination hotkey to send instead

136

137

Returns:

138

Function to remove the remapping

139

"""

140

```

141

142

## Usage Examples

143

144

### Basic Key Simulation

145

146

```python

147

import keyboard

148

149

# Simple key presses

150

keyboard.press_and_release('space')

151

keyboard.send('enter')

152

153

# Key combinations

154

keyboard.send('ctrl+c') # Copy

155

keyboard.send('ctrl+v') # Paste

156

keyboard.send('alt+tab') # Window switch

157

keyboard.send('ctrl+alt+del') # Secure attention sequence

158

159

# Multi-step sequences

160

keyboard.send('ctrl+f, hello, enter') # Find "hello"

161

```

162

163

### Text Typing

164

165

```python

166

import keyboard

167

168

# Basic text input

169

keyboard.write('Hello, World!')

170

171

# Text with special characters

172

keyboard.write('Café, naïve, résumé') # Unicode characters

173

174

# Controlled typing speed

175

keyboard.write('Slow typing...', delay=0.1) # 100ms between characters

176

177

# Platform-specific unicode handling

178

keyboard.write('Mathematical: ∑, ∞, π', exact=True) # Force unicode method

179

```

180

181

### Advanced Key State Management

182

183

```python

184

import keyboard

185

186

# Save current state

187

current_state = keyboard.stash_state()

188

189

# Perform some operations

190

keyboard.write('Some automated text')

191

keyboard.send('ctrl+s') # Save

192

193

# Restore original key state

194

keyboard.restore_state(current_state)

195

```

196

197

### Key Remapping

198

199

```python

200

import keyboard

201

202

# Remap Caps Lock to Ctrl

203

remove_remap = keyboard.remap_key('caps lock', 'ctrl')

204

205

print('Caps Lock now acts as Ctrl. Press ESC to exit.')

206

keyboard.wait('esc')

207

208

# Remove the remapping

209

remove_remap()

210

```

211

212

### Checking Key States

213

214

```python

215

import keyboard

216

217

def check_modifier_combo():

218

if keyboard.is_pressed('ctrl+shift'):

219

print('Ctrl+Shift is pressed!')

220

elif keyboard.is_pressed('ctrl'):

221

print('Ctrl is pressed')

222

elif keyboard.is_pressed('shift'):

223

print('Shift is pressed')

224

225

# Check continuously

226

while True:

227

check_modifier_combo()

228

if keyboard.is_pressed('esc'):

229

break

230

```

231

232

### Complex Automation Example

233

234

```python

235

import keyboard

236

import time

237

238

def automated_data_entry():

239

# Save current keyboard state

240

saved_state = keyboard.stash_state()

241

242

try:

243

# Type form data with delays

244

keyboard.write('John Doe', delay=0.05)

245

keyboard.send('tab')

246

time.sleep(0.1)

247

248

keyboard.write('john.doe@example.com', delay=0.03)

249

keyboard.send('tab')

250

time.sleep(0.1)

251

252

keyboard.write('555-123-4567', delay=0.05)

253

keyboard.send('tab')

254

255

# Submit form

256

keyboard.send('enter')

257

258

finally:

259

# Restore original keyboard state

260

keyboard.restore_modifiers(saved_state)

261

262

# Trigger automation with hotkey

263

keyboard.add_hotkey('ctrl+shift+f', automated_data_entry)

264

keyboard.wait('esc')

265

```

266

267

## Key Parsing and Utilities

268

269

```python { .api }

270

def key_to_scan_codes(key, error_if_missing=True):

271

"""

272

Returns a list of scan codes associated with this key (name or scan code).

273

274

Parameters:

275

- key: Key name, scan code, or list of keys

276

- error_if_missing: Raise error if key not found (default: True)

277

278

Returns:

279

tuple: Scan codes for the key

280

"""

281

282

def parse_hotkey(hotkey):

283

"""

284

Parses a user-provided hotkey into nested tuples representing the

285

parsed structure, with the bottom values being lists of scan codes.

286

287

Parameters:

288

- hotkey: Hotkey string to parse (e.g., 'ctrl+shift+a, alt+b')

289

290

Returns:

291

tuple: Parsed hotkey structure

292

"""

293

294

def normalize_name(name):

295

"""

296

Given a key name, clean up the string and convert to canonical

297

representation if one is known.

298

299

Parameters:

300

- name: Key name to normalize

301

302

Returns:

303

str: Normalized key name

304

"""

305

306

def is_modifier(key):

307

"""

308

Returns True if key is a scan code or name of a modifier key.

309

310

Parameters:

311

- key: Key name or scan code to check

312

313

Returns:

314

bool: True if key is a modifier

315

"""

316

317

def parse_hotkey_combinations(hotkey):

318

"""

319

Parses a user-provided hotkey. Instead of each step being a list of the

320

different scan codes for each key, each step is a list of all possible

321

combinations of those scan codes.

322

323

Parameters:

324

- hotkey: Hotkey string to parse

325

326

Returns:

327

tuple: All possible scan code combinations for the hotkey

328

329

Note: This is used internally for hotkey matching optimization.

330

"""

331

```

332

333

## Hotkey String Format

334

335

The keyboard package supports flexible hotkey string formats:

336

337

### Single Keys

338

- `'a'` - Letter key

339

- `'space'` - Named key

340

- `'enter'` - Special key

341

- `57` - Scan code

342

343

### Key Combinations

344

- `'ctrl+c'` - Modifier + key

345

- `'ctrl+shift+a'` - Multiple modifiers

346

- `'alt+F4'` - Case insensitive

347

348

### Multi-Step Sequences

349

- `'ctrl+c, ctrl+v'` - Copy then paste

350

- `'alt+tab, enter'` - Switch window then confirm

351

- `'win+r, notepad, enter'` - Open Run, type "notepad", press Enter

352

353

### Special Characters

354

- `'ctrl+plus'` - Use 'plus' for '+' symbol

355

- `'ctrl+comma'` - Use 'comma' for ',' symbol

356

- `'ctrl+space'` - Use 'space' for spacebar

357

358

### Delayed Execution

359

360

Execute functions with a delay without blocking the current thread.

361

362

```python { .api }

363

def call_later(fn, args=(), delay=0.001):

364

"""

365

Calls the provided function in a new thread after waiting some time.

366

Useful for giving the system some time to process an event, without blocking

367

the current execution flow.

368

369

Parameters:

370

- fn: Function to call

371

- args: Arguments to pass to function (default: empty tuple)

372

- delay: Delay in seconds before calling function (default: 0.001)

373

374

Examples:

375

call_later(print, args=['Hello after delay'])

376

call_later(lambda: keyboard.send('enter'), delay=0.5)

377

"""

378

```

379

380

## Platform Considerations

381

382

### Windows

383

- Full simulation support including unicode typing

384

- Event injection works with most applications

385

- Alt codes supported for unicode characters

386

387

### Linux

388

- Requires root privileges for key simulation

389

- Unicode typing through various input methods

390

- Some applications may not receive simulated events

391

392

### macOS

393

- Requires accessibility permissions

394

- Unicode typing through system services

395

- Limited support compared to other platforms

396

397

## Error Handling

398

399

Key simulation may fail due to:

400

- Insufficient privileges

401

- Platform security restrictions

402

- Invalid key names or scan codes

403

- Target application event blocking

404

405

The package will raise `ValueError` for invalid keys and `OSError` for platform-specific failures.