or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-application.mddata-types.mdindex.mdrule-development.mdrule-system.mdshell-integration.mduser-interface.mdutilities.md

utilities.mddocs/

0

# Utilities and Helpers

1

2

Common utility functions, decorators, and helper tools used throughout the application for caching, string matching, command manipulation, and application detection. These utilities provide essential functionality that supports the core correction system.

3

4

## Capabilities

5

6

### Caching and Memoization

7

8

Functions for improving performance through result caching and memoization.

9

10

```python { .api }

11

def memoize(fn):

12

"""

13

Decorator for function result caching.

14

15

Parameters:

16

- fn (callable): Function to memoize

17

18

Returns:

19

callable: Memoized version of the function

20

21

Caches function results based on arguments to avoid repeated computation.

22

Cache can be disabled by setting memoize.disabled = True.

23

24

Example:

25

@memoize

26

def expensive_function(arg1, arg2):

27

# Expensive computation

28

return result

29

"""

30

31

def cache(*depends_on):

32

"""

33

File-based caching decorator with dependency tracking.

34

35

Parameters:

36

- *depends_on (str): Files to monitor for cache invalidation

37

38

Returns:

39

callable: Decorator function that caches results

40

41

Caches function result in temporary file. Cache will be expired when

42

modification date of files from depends_on will be changed. Function

43

wrapped in cache should be arguments agnostic.

44

45

Example:

46

@cache('~/.thefuck/settings.py')

47

def get_expensive_settings():

48

# Expensive computation

49

return result

50

"""

51

```

52

53

### System and Application Detection

54

55

Functions for detecting system capabilities and applications.

56

57

```python { .api }

58

def which(program):

59

"""

60

Returns program path or None.

61

62

Parameters:

63

- program (str): Program name to locate

64

65

Returns:

66

str or None: Full path to program if found, None otherwise

67

68

Cross-platform implementation of 'which' command functionality.

69

Searches PATH for executable programs.

70

"""

71

72

def is_app(command, *app_names):

73

"""

74

Returns True if command is call to one of passed app names.

75

76

Parameters:

77

- command (Command): Command object to check

78

- *app_names (str): Application names to check against

79

80

Returns:

81

bool: True if command matches any of the app names

82

83

Checks if the command script starts with any of the specified

84

application names, handling both bare commands and commands with arguments.

85

86

Example:

87

cmd = Command("git status", "", "")

88

if is_app(cmd, 'git'):

89

print("This is a git command")

90

"""

91

92

def for_app(*app_names):

93

"""

94

Decorator that specifies matching script is for one of app names.

95

96

Parameters:

97

- *app_names (str): Application names to match against

98

99

Returns:

100

callable: Decorator function

101

102

Uses is_app internally to check if the command matches any of the

103

specified application names. Returns False if no match.

104

105

Example:

106

@for_app('docker', 'podman')

107

def container_correction(command, settings):

108

# Container-specific correction logic

109

return corrected_command

110

"""

111

```

112

113

### String Matching and Fuzzy Search

114

115

Functions for intelligent string matching and similarity detection.

116

117

```python { .api }

118

def get_closest(word, possibilities, n=3, cutoff=0.6, fallback_to_first=True):

119

"""

120

Returns closest match or just first from possibilities.

121

122

Parameters:

123

- word (str): Word to find matches for

124

- possibilities (list): List of possible matches

125

- n (int): Maximum number of matches to consider (default: 3)

126

- cutoff (float): Minimum similarity score (0.0-1.0, default: 0.6)

127

- fallback_to_first (bool): Return first possibility if no close match

128

129

Returns:

130

str or None: Best match or first possibility if fallback enabled

131

132

Uses difflib.get_close_matches for intelligent fuzzy matching.

133

Useful for correcting typos in command names and arguments.

134

"""

135

136

def get_all_executables():

137

"""

138

Returns list of all available executables and shell aliases.

139

140

Returns:

141

list: List of executable names and shell aliases

142

143

Searches PATH directories for executable files and includes shell aliases.

144

Excludes the thefuck alias itself to avoid self-reference. Results are

145

memoized for performance.

146

147

Used for intelligent command suggestions and corrections.

148

"""

149

```

150

151

### Command Manipulation

152

153

Functions for analyzing and modifying command strings.

154

155

```python { .api }

156

def replace_argument(script, from_, to):

157

"""

158

Replaces command line argument.

159

160

Parameters:

161

- script (str): Original command string

162

- from_ (str): Argument to replace

163

- to (str): Replacement argument

164

165

Returns:

166

str: Command with argument replaced

167

168

First tries to replace at the end of the command, then in the middle

169

with space boundaries to avoid partial replacements.

170

Example: replace_argument('git pul origin', 'pul', 'pull')

171

"""

172

173

def replace_command(command, broken, matched):

174

"""

175

Helper for *_no_command rules.

176

177

Parameters:

178

- command (Command): Command object containing the script

179

- broken (str): Broken command name to replace

180

- matched (list): List of possible correct command names

181

182

Returns:

183

list: List of corrected command strings

184

185

Uses fuzzy matching to find close matches and generates multiple

186

correction suggestions by replacing the broken command with matches.

187

"""

188

189

def eager(fn, *args, **kwargs):

190

"""

191

Decorator that converts generator to list.

192

193

Parameters:

194

- fn (callable): Function that returns a generator

195

- *args: Arguments to pass to function

196

- **kwargs: Keyword arguments to pass to function

197

198

Returns:

199

list: List containing all generator results

200

201

Forces immediate evaluation of generator functions.

202

"""

203

204

def get_all_matched_commands(stderr, separator='Did you mean'):

205

"""

206

Extracts command suggestions from error output.

207

208

Parameters:

209

- stderr (str): Error output containing suggestions

210

- separator (str): Text that indicates start of suggestions

211

212

Returns:

213

list: List of suggested commands

214

215

Parses command line tool error messages to extract suggested

216

corrections. Commonly used with tools that provide "did you mean"

217

style suggestions.

218

"""

219

220

def wrap_settings(params):

221

"""

222

Adds default values to settings if it not presented.

223

224

Parameters:

225

- params (dict): Default parameter values to add to settings

226

227

Returns:

228

callable: Decorator function

229

230

Decorator that ensures rule functions have access to default

231

settings values. Commonly used in rules that need specific

232

application paths or configuration values.

233

234

Example:

235

@wrap_settings({'apt': '/usr/bin/apt'})

236

def match(command, settings):

237

print(settings.apt)

238

"""

239

```

240

241

242

### Platform and Environment

243

244

Utility constants and functions for platform compatibility.

245

246

```python { .api }

247

DEVNULL = open(os.devnull, 'w')

248

"""

249

File object for null output redirection.

250

Cross-platform equivalent of /dev/null.

251

"""

252

253

def quote(text):

254

"""

255

Shell-safe quoting function.

256

257

Parameters:

258

- text (str): Text to quote for shell safety

259

260

Returns:

261

str: Properly quoted text

262

263

Platform-specific implementation:

264

- Python 2: Uses pipes.quote

265

- Python 3: Uses shlex.quote

266

"""

267

```

268

269

## Usage Examples

270

271

### Memoization for Performance

272

273

```python

274

from thefuck.utils import memoize

275

276

@memoize

277

def expensive_git_operation(repo_path):

278

"""Expensive operation that benefits from caching."""

279

# Simulate expensive operation

280

import subprocess

281

result = subprocess.run(['git', 'log', '--oneline'],

282

cwd=repo_path, capture_output=True, text=True)

283

return result.stdout.split('\n')

284

285

# First call: executes operation

286

commits1 = expensive_git_operation('/path/to/repo')

287

288

# Second call: returns cached result

289

commits2 = expensive_git_operation('/path/to/repo') # Much faster

290

291

# Disable caching temporarily

292

from thefuck.utils import memoize

293

memoize.disabled = True

294

commits3 = expensive_git_operation('/path/to/repo') # Executes again

295

memoize.disabled = False

296

```

297

298

### Application Detection

299

300

```python

301

from thefuck.utils import which, is_app, for_app

302

303

# Check if programs are available

304

git_path = which('git')

305

if git_path:

306

print(f"Git found at: {git_path}")

307

308

docker_path = which('docker')

309

if docker_path:

310

print(f"Docker found at: {docker_path}")

311

312

# Use decorators for app-specific functions

313

@for_app('git')

314

def handle_git_command(command, settings):

315

print(f"Handling git command: {command.script}")

316

317

@is_app('npm')

318

def handle_npm_command(command, settings):

319

print(f"Handling npm command: {command.script}")

320

```

321

322

### Fuzzy String Matching

323

324

```python

325

from thefuck.utils import get_closest, get_all_matched

326

327

# Find closest match for typos

328

git_commands = ['push', 'pull', 'commit', 'checkout', 'branch', 'merge']

329

closest = get_closest('pul', git_commands)

330

print(f"Did you mean: {closest}") # "pull"

331

332

# Get all possible matches

333

typo = 'comit'

334

all_matches = get_all_matched(typo, git_commands, cutoff=0.4)

335

print(f"Possible matches: {all_matches}") # ['commit']

336

337

# Directory name correction

338

dirs = ['Documents', 'Downloads', 'Desktop', 'Pictures']

339

corrected = get_closest('Documnets', dirs)

340

print(f"Corrected directory: {corrected}") # "Documents"

341

```

342

343

### Command Manipulation

344

345

```python

346

from thefuck.utils import replace_argument, replace_command, add_argument

347

348

# Fix command typos

349

original = "git pul origin main"

350

fixed = replace_argument(original, 'pul', 'pull')

351

print(f"Fixed: {fixed}") # "git pull origin main"

352

353

# Fix command name typos

354

typo_cmd = "gti status"

355

fixed_cmd = replace_command(typo_cmd, 'gti', 'git')

356

print(f"Fixed command: {fixed_cmd}") # "git status"

357

358

# Add missing arguments

359

incomplete = "docker run image"

360

complete = add_argument(incomplete, '--rm')

361

print(f"Complete: {complete}") # "docker run --rm image"

362

```

363

364

### History Integration

365

366

```python

367

from thefuck.utils import get_valid_history_without_current

368

from thefuck.types import Command

369

370

# Get relevant history

371

current_cmd = Command("git push origin main", "", "error output")

372

history = get_valid_history_without_current(current_cmd)

373

374

print("Recent commands (excluding current):")

375

for cmd in history[:5]: # Show last 5

376

print(f" {cmd}")

377

```

378

379

### Safe Shell Quoting

380

381

```python

382

from thefuck.utils import quote

383

384

# Safely quote arguments for shell execution

385

filename = "file with spaces.txt"

386

safe_filename = quote(filename)

387

command = f"cat {safe_filename}"

388

print(f"Safe command: {command}") # cat 'file with spaces.txt'

389

390

# Handle special characters

391

special_arg = "arg with $pecial char&"

392

safe_arg = quote(special_arg)

393

print(f"Safe argument: {safe_arg}")

394

```

395

396

### Caching with Persistence

397

398

```python

399

from thefuck.utils import cache

400

import requests

401

402

@cache

403

def fetch_api_data(url):

404

"""Expensive API call that benefits from persistent caching."""

405

response = requests.get(url)

406

return response.json()

407

408

# First call: makes HTTP request

409

data1 = fetch_api_data('https://api.example.com/data')

410

411

# Second call (even in different session): uses cached data

412

data2 = fetch_api_data('https://api.example.com/data') # No HTTP request

413

```

414

415

## Performance Considerations

416

417

### Memoization Guidelines

418

- Use for CPU-intensive pure functions

419

- Avoid for functions with side effects

420

- Consider memory usage for large result sets

421

- Disable during testing if needed

422

423

### Caching Best Practices

424

- Use persistent cache for cross-session data

425

- Consider cache invalidation strategies

426

- Monitor cache size and cleanup as needed

427

- Use appropriate cache keys

428

429

### String Matching Optimization

430

- Adjust cutoff values for accuracy vs. performance

431

- Pre-filter possibilities when working with large lists

432

- Consider caching fuzzy match results for repeated queries

433

434

These utilities form the foundation that enables thefuck's intelligent command correction and provide the performance optimizations necessary for responsive user experience.