0
# Shell Interface
1
2
## Overview
3
4
Xonsh's shell interface provides interactive command execution, pipeline management, and shell session control. The shell supports multiple backends (readline, prompt-toolkit, dumb) and provides comprehensive command processing with Python integration.
5
6
## Core Shell Classes
7
8
### Shell
9
```python { .api }
10
from xonsh.shell import Shell
11
12
class Shell:
13
"""Main shell interface for xonsh."""
14
15
def __init__(self, execer=None, ctx=None, **kwargs):
16
"""Initialize shell.
17
18
Parameters
19
----------
20
execer : Execer, optional
21
Code executer instance
22
ctx : dict, optional
23
Execution context
24
**kwargs
25
Additional shell configuration
26
"""
27
28
def cmdloop(self, intro=None) -> None:
29
"""Start the interactive command loop.
30
31
Parameters
32
----------
33
intro : str, optional
34
Introduction message to display
35
"""
36
37
def default(self, line: str) -> None:
38
"""Execute a line of input.
39
40
Parameters
41
----------
42
line : str
43
Command line to execute
44
"""
45
46
def precmd(self, line: str) -> str:
47
"""Process command before execution.
48
49
Parameters
50
----------
51
line : str
52
Raw command line
53
54
Returns
55
-------
56
str
57
Processed command line
58
"""
59
60
def postcmd(self, stop: bool, line: str) -> bool:
61
"""Process command after execution.
62
63
Parameters
64
----------
65
stop : bool
66
Whether to stop the command loop
67
line : str
68
Executed command line
69
70
Returns
71
-------
72
bool
73
Whether to continue the command loop
74
"""
75
```
76
77
### Shell Backends
78
79
#### ReadlineShell
80
```python { .api }
81
from xonsh.shells.readline_shell import ReadlineShell
82
83
class ReadlineShell(Shell):
84
"""Shell using Python's readline library."""
85
86
def __init__(self, **kwargs):
87
"""Initialize readline shell."""
88
89
def singleline(self, store_in_history=True, **kwargs) -> str:
90
"""Read a single line of input.
91
92
Parameters
93
----------
94
store_in_history : bool, default True
95
Whether to store input in history
96
97
Returns
98
-------
99
str
100
Input line
101
"""
102
```
103
104
#### PromptToolkitShell
105
```python { .api }
106
from xonsh.shells.ptk_shell import PromptToolkitShell
107
108
class PromptToolkitShell(Shell):
109
"""Enhanced shell using prompt-toolkit library."""
110
111
def __init__(self, **kwargs):
112
"""Initialize prompt-toolkit shell."""
113
114
def singleline(self, store_in_history=True, **kwargs) -> str:
115
"""Read a single line with enhanced features.
116
117
Parameters
118
----------
119
store_in_history : bool, default True
120
Whether to store in history
121
122
Returns
123
-------
124
str
125
Input line with syntax highlighting and completion
126
"""
127
```
128
129
## Shell Configuration
130
131
### Shell Selection
132
```python { .api }
133
from xonsh.platform import best_shell_type
134
135
# Automatic shell selection
136
shell_type = best_shell_type() # Returns 'prompt_toolkit', 'readline', or 'dumb'
137
138
# Manual shell creation
139
from xonsh.shell import Shell
140
shell = Shell(shell_type='prompt_toolkit')
141
```
142
143
### Shell Environment Variables
144
```python { .api }
145
from xonsh.built_ins import XSH
146
147
# Key shell configuration variables
148
env = XSH.env
149
env['SHELL_TYPE'] = 'prompt_toolkit' # Shell backend to use
150
env['XONSH_SHOW_TRACEBACK'] = True # Show Python tracebacks
151
env['COMPLETIONS_CONFIRM'] = True # Confirm before completing
152
env['COMPLETION_QUERY_LIMIT'] = 100 # Max completions to show
153
env['MULTILINE_PROMPT'] = ' ' # Continuation prompt
154
env['PROMPT'] = '{cwd} $ ' # Primary prompt format
155
```
156
157
## Command Execution
158
159
### Interactive Execution
160
```python { .api }
161
from xonsh.shell import Shell
162
163
shell = Shell()
164
165
# Single command execution
166
shell.default("ls -la")
167
shell.default("echo $HOME")
168
shell.default("python -c 'print(2+2)'")
169
170
# Multi-line command
171
shell.default("""
172
for i in range(3):
173
print(f"Count: {i}")
174
""")
175
```
176
177
### Programmatic Execution
178
```python { .api }
179
from xonsh.built_ins import XSH
180
181
# Execute through XSH session
182
result = XSH.execer.eval("ls | wc -l")
183
XSH.execer.exec("MY_VAR = 'hello'")
184
185
# Execution with context
186
ctx = {'x': 10, 'y': 20}
187
result = XSH.execer.eval("x + y", ctx=ctx) # Returns 30
188
```
189
190
### Command Pipeline Handling
191
```python { .api }
192
from xonsh.procs.pipelines import run_subproc
193
from xonsh.procs.specs import SubprocSpec
194
195
# Create subprocess specification
196
spec = SubprocSpec(['ls', '-la'], captured='stdout')
197
result = run_subproc(spec)
198
199
# Pipeline execution
200
from xonsh.built_ins import subproc_captured_stdout
201
output = subproc_captured_stdout(['ls', '-la']) # Captured output
202
```
203
204
## Event Hooks
205
206
### Command Events
207
```python { .api }
208
from xonsh.events import events
209
210
@events.on_transform_command
211
def transform_command(cmd: str) -> str:
212
"""Transform command before parsing.
213
214
Parameters
215
----------
216
cmd : str
217
Original command
218
219
Returns
220
-------
221
str
222
Transformed command
223
"""
224
return cmd.replace('ll', 'ls -la')
225
226
@events.on_precommand
227
def before_command(cmd: str) -> None:
228
"""Called before command execution.
229
230
Parameters
231
----------
232
cmd : str
233
Command to be executed
234
"""
235
print(f"Executing: {cmd}")
236
237
@events.on_postcommand
238
def after_command(cmd: str, rtn: int, out: str, ts: list) -> None:
239
"""Called after command execution.
240
241
Parameters
242
----------
243
cmd : str
244
Executed command
245
rtn : int
246
Return code (0 for success)
247
out : str or None
248
Command output if captured
249
ts : list
250
Timestamps [start, end]
251
"""
252
if rtn != 0:
253
print(f"Command failed with code {rtn}")
254
255
@events.on_command_not_found
256
def command_not_found(cmd: list[str]) -> None:
257
"""Called when command is not found.
258
259
Parameters
260
----------
261
cmd : list[str]
262
Command arguments that were not found
263
"""
264
print(f"Command not found: {' '.join(cmd)}")
265
```
266
267
### Prompt Events
268
```python { .api }
269
@events.on_pre_prompt_format
270
def before_prompt_format() -> None:
271
"""Called before prompt formatting."""
272
pass
273
274
@events.on_pre_prompt
275
def before_prompt() -> None:
276
"""Called just before showing prompt."""
277
pass
278
279
@events.on_post_prompt
280
def after_prompt() -> None:
281
"""Called after prompt input is received."""
282
pass
283
```
284
285
## Advanced Shell Features
286
287
### Custom Shell Creation
288
```python { .api }
289
from xonsh.shells.base_shell import BaseShell
290
291
class CustomShell(BaseShell):
292
"""Custom shell implementation."""
293
294
def __init__(self, **kwargs):
295
super().__init__(**kwargs)
296
297
def cmdloop(self, intro=None):
298
"""Custom command loop implementation."""
299
while True:
300
try:
301
line = self.singleline()
302
if line.strip() == 'exit':
303
break
304
self.default(line)
305
except KeyboardInterrupt:
306
print("^C")
307
except EOFError:
308
break
309
310
def singleline(self, **kwargs) -> str:
311
"""Custom input implementation."""
312
return input(self.format_prompt())
313
314
def format_prompt(self) -> str:
315
"""Format custom prompt."""
316
return "custom> "
317
```
318
319
### Shell State Management
320
```python { .api }
321
from xonsh.built_ins import XSH
322
323
# Access shell state
324
shell = XSH.shell
325
if shell:
326
# Check if shell is interactive
327
is_interactive = hasattr(shell, 'cmdloop')
328
329
# Access shell history
330
if hasattr(shell, 'history'):
331
recent_commands = shell.history.items()
332
333
# Shell execution context
334
ctx = shell.ctx if hasattr(shell, 'ctx') else {}
335
```
336
337
### Error Handling
338
```python { .api }
339
from xonsh.tools import XonshError, print_exception
340
341
try:
342
XSH.execer.eval("invalid_syntax }")
343
except SyntaxError as e:
344
print_exception() # Pretty-print exception
345
except XonshError as e:
346
print(f"Xonsh error: {e}")
347
```
348
349
## Shell Integration
350
351
### With Python Code
352
```python { .api }
353
# Seamless Python integration in shell
354
"""
355
In xonsh shell:
356
>>> import sys
357
>>> sys.version
358
>>> len([x for x in range(10) if x % 2 == 0])
359
>>> $(echo "Shell command")
360
>>> for i in range(3):
361
... echo f"Hello {i}"
362
"""
363
364
# Programmatic integration
365
def run_shell_command(cmd):
366
"""Run shell command and return result."""
367
from xonsh.built_ins import subproc_captured_stdout
368
return subproc_captured_stdout(cmd)
369
370
result = run_shell_command(['ls', '-la'])
371
```
372
373
### Job Control
374
```python { .api }
375
from xonsh.procs.jobs import jobs, fg, bg, disown
376
377
# List active jobs
378
active_jobs = jobs()
379
380
# Foreground/background job control
381
fg(1) # Bring job 1 to foreground
382
bg(1) # Send job 1 to background
383
disown(1) # Disown job 1
384
385
# Job status checking
386
from xonsh.built_ins import XSH
387
if hasattr(XSH, 'all_jobs'):
388
for job in XSH.all_jobs:
389
print(f"Job {job.obj}: {job.status}")
390
```
391
392
The shell interface provides the foundation for all interactive xonsh usage, supporting both simple command execution and complex Python-shell integration scenarios.