0
# Completion
1
2
## Overview
3
4
Xonsh provides a sophisticated tab completion system with pluggable completers for commands, paths, Python objects, and custom contexts. The completion system supports both simple string completions and rich completions with descriptions, styling, and advanced filtering.
5
6
## Core Completion Classes
7
8
### Completer
9
```python { .api }
10
from xonsh.completer import Completer
11
from xonsh.parsers.completion_context import CompletionContext
12
13
class Completer:
14
"""Main completion engine for xonsh."""
15
16
def __init__(self):
17
"""Initialize completer with context parser."""
18
self.context_parser = CompletionContextParser()
19
20
def parse(self, text: str, cursor_index: int = None, ctx: dict = None) -> CompletionContext:
21
"""Parse text to create completion context.
22
23
Parameters
24
----------
25
text : str
26
Multi-line text to parse
27
cursor_index : int, optional
28
Cursor position (defaults to end of text)
29
ctx : dict, optional
30
Execution context
31
32
Returns
33
-------
34
CompletionContext
35
Parsed completion context
36
"""
37
38
def complete(self, prefix: str, line: str, begidx: int, endidx: int,
39
ctx: dict = None, multiline_text: str = None,
40
cursor_index: int = None,
41
completion_context: CompletionContext = None) -> list[str]:
42
"""Generate completions for given context.
43
44
Parameters
45
----------
46
prefix : str
47
Text to complete
48
line : str
49
Full line containing prefix
50
begidx : int
51
Start index of prefix in line
52
endidx : int
53
End index of prefix in line
54
ctx : dict, optional
55
Execution context
56
multiline_text : str, optional
57
Complete multi-line text
58
cursor_index : int, optional
59
Cursor position
60
completion_context : CompletionContext, optional
61
Pre-parsed completion context
62
63
Returns
64
-------
65
list[str]
66
List of completion strings or RichCompletion objects
67
"""
68
69
def complete_line(self, text: str) -> list[str]:
70
"""Complete when cursor is at end of line.
71
72
Parameters
73
----------
74
text : str
75
Text to complete
76
77
Returns
78
-------
79
list[str]
80
List of completions
81
"""
82
83
# Usage examples
84
completer = Completer()
85
86
# Simple completion
87
completions = completer.complete("gi", "git status", 0, 2)
88
89
# Line completion (cursor at end)
90
completions = completer.complete_line("ls /usr/")
91
92
# Advanced completion with context
93
ctx = {'myvar': 'value'}
94
completions = completer.complete("myv", "print(myvar)", 6, 9, ctx=ctx)
95
```
96
97
### RichCompletion
98
```python { .api }
99
from xonsh.completers.tools import RichCompletion, Completion
100
101
class RichCompletion(str):
102
"""Enhanced completion with metadata and styling."""
103
104
def __init__(self, value: str,
105
prefix_len: int = None,
106
display: str = None,
107
description: str = "",
108
style: str = "",
109
append_closing_quote: bool = True,
110
append_space: bool = False):
111
"""Create rich completion.
112
113
Parameters
114
----------
115
value : str
116
Actual completion text
117
prefix_len : int, optional
118
Length of prefix to replace
119
display : str, optional
120
Text to display in completion menu
121
description : str, default ""
122
Detailed description of completion
123
style : str, default ""
124
Style string for prompt-toolkit
125
append_closing_quote : bool, default True
126
Whether to append closing quote
127
append_space : bool, default False
128
Whether to append space after completion
129
"""
130
131
# Rich completion examples
132
basic_completion = RichCompletion("status", description="Show repository status")
133
styled_completion = RichCompletion("branch",
134
display="branch (git)",
135
description="List, create, or delete branches",
136
style="bold blue")
137
path_completion = RichCompletion("/home/user/",
138
prefix_len=5, # Replace last 5 chars
139
append_space=False)
140
```
141
142
## Built-in Completers
143
144
### Command Completion
145
```python { .api }
146
from xonsh.completers.commands import complete_command
147
148
def complete_command(prefix: str, line: str, start: int, end: int,
149
ctx: dict) -> set[str]:
150
"""Complete command names.
151
152
Parameters
153
----------
154
prefix : str
155
Command prefix to complete
156
line : str
157
Full command line
158
start : int
159
Start position of prefix
160
end : int
161
End position of prefix
162
ctx : dict
163
Execution context
164
165
Returns
166
-------
167
set[str]
168
Set of command completions
169
"""
170
171
# Command completion automatically handles:
172
# - Executable files in PATH
173
# - Python functions and variables in context
174
# - Xonsh aliases
175
# - Built-in commands
176
```
177
178
### Path Completion
179
```python { .api }
180
from xonsh.completers.path import complete_path
181
182
def complete_path(prefix: str, line: str, start: int, end: int,
183
ctx: dict) -> set[RichCompletion]:
184
"""Complete file and directory paths.
185
186
Parameters
187
----------
188
prefix : str
189
Path prefix to complete
190
line : str
191
Full command line
192
start : int
193
Start position of prefix
194
end : int
195
End position of prefix
196
ctx : dict
197
Execution context
198
199
Returns
200
-------
201
set[RichCompletion]
202
Set of path completions with metadata
203
"""
204
205
# Path completion features:
206
# - File and directory names
207
# - Hidden file support (when prefix starts with .)
208
# - Tilde expansion (~/)
209
# - Environment variable expansion ($VAR/)
210
# - Quote handling for spaces
211
```
212
213
### Python Completion
214
```python { .api }
215
from xonsh.completers.python import complete_python
216
217
def complete_python(prefix: str, line: str, start: int, end: int,
218
ctx: dict) -> set[str]:
219
"""Complete Python expressions.
220
221
Parameters
222
----------
223
prefix : str
224
Python expression prefix
225
line : str
226
Full line
227
start : int
228
Start position
229
end : int
230
End position
231
ctx : dict
232
Execution context with available names
233
234
Returns
235
-------
236
set[str]
237
Python attribute/name completions
238
"""
239
240
# Python completion handles:
241
# - Variable names from context
242
# - Module attributes (os.path.*)
243
# - Object methods and attributes
244
# - Import statements
245
# - Function signatures
246
```
247
248
## Custom Completers
249
250
### Creating Custom Completers
251
```python { .api }
252
from xonsh.completers.tools import contextual_completer, exclusive_completer
253
254
@contextual_completer
255
def my_completer(context: CompletionContext) -> set[str]:
256
"""Custom contextual completer.
257
258
Parameters
259
----------
260
context : CompletionContext
261
Completion context with command and argument info
262
263
Returns
264
-------
265
set[str]
266
Set of completions for this context
267
"""
268
if context.command and context.command.arg_index == 1:
269
# Complete first argument to any command
270
return {'option1', 'option2', 'option3'}
271
return set()
272
273
@exclusive_completer
274
def exclusive_completer_example(context: CompletionContext) -> set[str]:
275
"""Exclusive completer that prevents other completers.
276
277
Returns
278
-------
279
set[str]
280
Exclusive set of completions
281
"""
282
if context.command and context.command.name == 'mycommand':
283
return {'exclusive1', 'exclusive2'}
284
return set()
285
286
# Register completers
287
from xonsh.built_ins import XSH
288
XSH.completers['my_completer'] = my_completer
289
XSH.completers['exclusive'] = exclusive_completer_example
290
```
291
292
### Completer Registration
293
```python { .api }
294
from xonsh.built_ins import XSH
295
296
def register_completer(name: str, completer_func):
297
"""Register a completer function.
298
299
Parameters
300
----------
301
name : str
302
Completer name
303
completer_func : callable
304
Completer function
305
"""
306
XSH.completers[name] = completer_func
307
308
def unregister_completer(name: str):
309
"""Remove a completer.
310
311
Parameters
312
----------
313
name : str
314
Completer name to remove
315
"""
316
if name in XSH.completers:
317
del XSH.completers[name]
318
319
# Example: Git branch completer
320
def git_branch_completer(context):
321
"""Complete git branch names."""
322
if (context.command and
323
context.command.name == 'git' and
324
len(context.command.args) > 0 and
325
context.command.args[0] in ['checkout', 'branch', 'merge']):
326
327
try:
328
from xonsh.built_ins import subproc_captured_stdout
329
branches = subproc_captured_stdout(['git', 'branch'])
330
return {b.strip('* ') for b in branches.split('\n') if b.strip()}
331
except:
332
return set()
333
return set()
334
335
register_completer('git_branches', git_branch_completer)
336
```
337
338
## Advanced Completion Features
339
340
### Completion Context Analysis
341
```python { .api }
342
from xonsh.parsers.completion_context import CompletionContext, CommandContext
343
344
def analyze_completion_context(context: CompletionContext):
345
"""Analyze completion context for decision making.
346
347
Parameters
348
----------
349
context : CompletionContext
350
Context to analyze
351
"""
352
353
# Check if completing a command name
354
if context.command and context.command.arg_index == 0:
355
print("Completing command name")
356
357
# Check if completing command arguments
358
elif context.command and context.command.arg_index > 0:
359
print(f"Completing argument {context.command.arg_index}")
360
print(f"Command: {context.command.name}")
361
print(f"Previous args: {context.command.args}")
362
363
# Check if completing Python expression
364
elif context.python:
365
print("Completing Python expression")
366
print(f"Prefix: {context.python.prefix}")
367
368
# Access line context
369
print(f"Line: {context.line}")
370
print(f"Cursor position: {context.cursor_index}")
371
```
372
373
### Dynamic Completion Loading
374
```python { .api }
375
from xonsh.completers.bash_completion import bash_complete_line
376
377
def load_bash_completions():
378
"""Load bash completion scripts."""
379
# Bash completion integration
380
try:
381
completions = bash_complete_line("git che", 7)
382
return completions
383
except:
384
return []
385
386
def load_external_completions(command: str) -> list[str]:
387
"""Load completions from external sources.
388
389
Parameters
390
----------
391
command : str
392
Command to get completions for
393
394
Returns
395
-------
396
list[str]
397
External completions
398
"""
399
# Could integrate with:
400
# - Bash completion scripts
401
# - Zsh completion functions
402
# - Command-specific completion APIs
403
# - Online completion services
404
405
external_completions = []
406
407
# Example: Load from completion file
408
completion_file = f"/usr/share/completions/{command}"
409
try:
410
with open(completion_file) as f:
411
external_completions = f.read().strip().split('\n')
412
except:
413
pass
414
415
return external_completions
416
```
417
418
### Completion Filtering and Ranking
419
```python { .api }
420
from xonsh.completers.tools import get_filter_function
421
422
def filter_completions(completions: list[str], prefix: str) -> list[str]:
423
"""Filter completions based on prefix and settings.
424
425
Parameters
426
----------
427
completions : list[str]
428
Raw completions to filter
429
prefix : str
430
Prefix to match against
431
432
Returns
433
-------
434
list[str]
435
Filtered completions
436
"""
437
filter_func = get_filter_function() # Respects CASE_SENSITIVE_COMPLETIONS
438
return [c for c in completions if filter_func(c, prefix)]
439
440
def rank_completions(completions: list[str], prefix: str) -> list[str]:
441
"""Rank completions by relevance.
442
443
Parameters
444
----------
445
completions : list[str]
446
Completions to rank
447
prefix : str
448
User input prefix
449
450
Returns
451
-------
452
list[str]
453
Ranked completions (best first)
454
"""
455
# Simple ranking by prefix match quality
456
exact_matches = [c for c in completions if c.startswith(prefix)]
457
fuzzy_matches = [c for c in completions if prefix.lower() in c.lower() and c not in exact_matches]
458
459
return sorted(exact_matches) + sorted(fuzzy_matches)
460
```
461
462
## Completion Configuration
463
464
### Environment Variables
465
```python { .api }
466
from xonsh.built_ins import XSH
467
468
# Key completion settings
469
env = XSH.env
470
env['CASE_SENSITIVE_COMPLETIONS'] = False # Case sensitivity
471
env['COMPLETIONS_CONFIRM'] = True # Confirm ambiguous completions
472
env['COMPLETION_QUERY_LIMIT'] = 100 # Max completions to show
473
env['COMPLETIONS_DISPLAY_VALUE'] = 'single' # Display mode
474
env['COMPLETIONS_MENU_ROWS'] = 5 # Menu height
475
env['BASH_COMPLETIONS'] = ['/usr/share/bash-completion/bash_completion'] # Bash completion files
476
```
477
478
### Completer Management
479
```python { .api }
480
from xonsh.built_ins import XSH
481
482
# List available completers
483
available_completers = list(XSH.completers.keys())
484
485
# Enable/disable specific completers
486
def toggle_completer(name: str, enabled: bool):
487
"""Enable or disable a completer."""
488
if enabled and name in XSH.completers:
489
# Completer is already registered
490
pass
491
elif not enabled and name in XSH.completers:
492
# Temporarily disable by removing
493
backup_completer = XSH.completers.pop(name)
494
# Store for potential re-enabling
495
XSH._disabled_completers = getattr(XSH, '_disabled_completers', {})
496
XSH._disabled_completers[name] = backup_completer
497
498
# Get completion statistics
499
def get_completion_stats():
500
"""Get completion system statistics."""
501
return {
502
'total_completers': len(XSH.completers),
503
'completer_names': list(XSH.completers.keys()),
504
'case_sensitive': XSH.env.get('CASE_SENSITIVE_COMPLETIONS'),
505
'query_limit': XSH.env.get('COMPLETION_QUERY_LIMIT'),
506
}
507
```
508
509
The completion system provides extensive customization options for creating domain-specific completion experiences, integrating with external tools, and providing rich interactive feedback to users.