0
# Advanced Features
1
2
Extended functionality including interactive editing, token manipulation, custom dispatching, and help system customization.
3
4
## Capabilities
5
6
### Interactive Text Editing
7
8
Launch external text editors for interactive input.
9
10
```python { .api }
11
def edit(
12
text: str = "",
13
editor: str | None = None,
14
suffix: str = ".txt",
15
require_save: bool = True,
16
require_change: bool = False
17
) -> str:
18
"""
19
Launch text editor for interactive editing.
20
21
Parameters
22
----------
23
text
24
Initial text content for editor
25
editor
26
Editor command to use. If None, uses $EDITOR environment variable
27
suffix
28
File suffix for temporary file
29
require_save
30
Whether user must save the file
31
require_change
32
Whether user must change the content
33
34
Returns
35
-------
36
str
37
Edited text content
38
39
Raises
40
------
41
EditorNotFoundError
42
If no editor is available
43
EditorDidNotSaveError
44
If user didn't save and require_save=True
45
EditorDidNotChangeError
46
If user didn't change content and require_change=True
47
"""
48
```
49
50
### Token Utilities
51
52
Utilities for working with command-line tokens and parsing.
53
54
```python { .api }
55
def env_var_split(value: str, type_: type) -> list[str]:
56
"""
57
Split environment variable value based on target type.
58
59
Parameters
60
----------
61
value
62
Environment variable string value
63
type_
64
Target type that determines splitting behavior
65
66
Returns
67
-------
68
list[str]
69
List of string tokens for conversion
70
"""
71
72
def default_name_transform(name: str) -> str:
73
"""
74
Convert Python identifier to CLI token format.
75
76
Parameters
77
----------
78
name
79
Python identifier (e.g., "my_parameter")
80
81
Returns
82
-------
83
str
84
CLI token format (e.g., "--my-parameter")
85
"""
86
87
UNSET: object
88
"""Sentinel value indicating no data provided."""
89
```
90
91
### Help System Customization
92
93
Rich panel creation for custom help and error display.
94
95
```python { .api }
96
def CycloptsPanel(
97
content: str,
98
*,
99
title: str | None = None,
100
border_style: str = "red",
101
padding: tuple[int, int] = (0, 1),
102
**kwargs
103
) -> Panel:
104
"""
105
Create Rich panel for Cyclopts help and error display.
106
107
Parameters
108
----------
109
content
110
Panel content text
111
title
112
Panel title
113
border_style
114
Rich border style name
115
padding
116
Panel padding (vertical, horizontal)
117
**kwargs
118
Additional Rich Panel parameters
119
120
Returns
121
-------
122
Panel
123
Rich Panel object for display
124
"""
125
```
126
127
### Custom Dispatching Protocol
128
129
Protocol for implementing custom command dispatching logic.
130
131
```python { .api }
132
class Dispatcher:
133
def __call__(
134
self,
135
command: Callable[..., Any],
136
bound: inspect.BoundArguments,
137
ignored: dict[str, Any],
138
/
139
) -> Any:
140
"""
141
Custom dispatcher protocol for command execution.
142
143
Parameters
144
----------
145
command
146
Function to dispatch/execute
147
bound
148
Bound arguments from parsing
149
ignored
150
Ignored/unused arguments
151
152
Returns
153
-------
154
Any
155
Result of function execution
156
"""
157
```
158
159
### Advanced App Configuration
160
161
Extended configuration options for App customization.
162
163
```python { .api }
164
class CycloptsConfig:
165
def __init__(
166
self,
167
*,
168
console: Console | None = None,
169
show: bool = True,
170
group: Group | None = None,
171
name: str | tuple[str, ...] | None = None,
172
help: str | None = None,
173
negative: str | Iterable[str] | None = None,
174
converter: Callable | None = None,
175
validator: Callable | list[Callable] | None = None,
176
env_var: str | Iterable[str] | None = None,
177
**kwargs
178
):
179
"""
180
Advanced configuration options for Cyclopts components.
181
182
Parameters
183
----------
184
console
185
Rich console for output
186
show
187
Whether to show in help
188
group
189
Grouping configuration
190
name
191
Name override
192
help
193
Help text
194
negative
195
Negative flag names
196
converter
197
Custom converter function
198
validator
199
Validation functions
200
env_var
201
Environment variable names
202
"""
203
```
204
205
### Interactive Shell Mode
206
207
Start interactive shell for applications.
208
209
```python { .api }
210
def interactive_shell(app: App) -> None:
211
"""
212
Start interactive shell mode for an application.
213
214
Parameters
215
----------
216
app
217
App instance to run in interactive mode
218
"""
219
```
220
221
### Version Handling
222
223
Flexible version display and management.
224
225
```python { .api }
226
def version_print(app: App) -> None:
227
"""
228
Print application version information.
229
230
Parameters
231
----------
232
app
233
App instance with version information
234
"""
235
236
def resolve_version_format(version: str | Callable[[], str]) -> str:
237
"""
238
Resolve version string from string or callable.
239
240
Parameters
241
----------
242
version
243
Version string or callable that returns version
244
245
Returns
246
-------
247
str
248
Resolved version string
249
"""
250
```
251
252
## Usage Examples
253
254
### Interactive Text Editing
255
256
```python
257
from cyclopts import App, edit
258
259
app = App()
260
261
@app.command
262
def create_message():
263
"""Create a message using text editor."""
264
content = edit(
265
text="# Enter your message here\n",
266
suffix=".md",
267
require_change=True
268
)
269
print("Message created:")
270
print(content)
271
272
@app.command
273
def edit_config():
274
"""Edit configuration interactively."""
275
current_config = '{"timeout": 30, "retries": 3}'
276
new_config = edit(
277
text=current_config,
278
suffix=".json",
279
require_save=True
280
)
281
print("Updated configuration:")
282
print(new_config)
283
```
284
285
### Custom Dispatcher
286
287
```python
288
from cyclopts import App
289
from cyclopts.protocols import Dispatcher
290
import asyncio
291
import inspect
292
293
class AsyncDispatcher:
294
"""Custom dispatcher that handles async functions."""
295
296
def __call__(self, func, bound_arguments, app):
297
if inspect.iscoroutinefunction(func):
298
return asyncio.run(func(*bound_arguments.args, **bound_arguments.kwargs))
299
else:
300
return func(*bound_arguments.args, **bound_arguments.kwargs)
301
302
app = App(dispatcher=AsyncDispatcher())
303
304
@app.command
305
async def async_task(duration: int = 5):
306
"""Run an async task."""
307
print(f"Starting async task for {duration} seconds...")
308
await asyncio.sleep(duration)
309
print("Async task completed!")
310
```
311
312
### Rich Help Customization
313
314
```python
315
from cyclopts import App, CycloptsPanel, Group
316
from rich.panel import Panel
317
318
# Custom group with panel styling
319
custom_group = Group(
320
"advanced",
321
"Advanced Options",
322
"Advanced configuration and debugging options",
323
panel=Panel.fit("Advanced Settings", border_style="blue")
324
)
325
326
app = App(group_parameters=custom_group)
327
328
@app.command
329
def deploy(
330
service: str,
331
debug: bool = False,
332
dry_run: bool = False
333
):
334
"""Deploy service with custom help styling."""
335
if debug:
336
print("Debug mode enabled")
337
if dry_run:
338
print("Dry run mode - no actual deployment")
339
print(f"Deploying {service}")
340
```
341
342
### Interactive Shell Mode
343
344
```python
345
from cyclopts import App
346
347
app = App(name="myshell")
348
349
@app.command
350
def status():
351
"""Show system status."""
352
print("System is running")
353
354
@app.command
355
def restart():
356
"""Restart the system."""
357
print("Restarting...")
358
359
@app.command
360
def shell():
361
"""Start interactive shell."""
362
app.interactive_shell()
363
364
if __name__ == "__main__":
365
app()
366
```
367
368
### Environment Variable Integration
369
370
```python
371
from cyclopts import App, env_var_split
372
import os
373
374
app = App()
375
376
@app.command
377
def process_files():
378
"""Process files from environment variable."""
379
file_list_env = os.getenv("FILE_LIST", "")
380
if file_list_env:
381
files = env_var_split(file_list_env, list[str])
382
print(f"Processing {len(files)} files:")
383
for file in files:
384
print(f" - {file}")
385
else:
386
print("No files specified in FILE_LIST environment variable")
387
388
# Usage: FILE_LIST="file1.txt,file2.txt,file3.txt" python script.py process-files
389
```
390
391
### Custom Name Transformation
392
393
```python
394
from cyclopts import App
395
396
def custom_name_transform(name: str) -> str:
397
"""Transform Python names to UPPERCASE CLI names."""
398
return f"--{name.upper().replace('_', '-')}"
399
400
app = App(name_transform=custom_name_transform)
401
402
@app.command
403
def process_data(
404
input_file: str,
405
max_workers: int = 4,
406
enable_caching: bool = False
407
):
408
"""Process data with custom name transformation."""
409
# CLI will have --INPUT-FILE, --MAX-WORKERS, --ENABLE-CACHING
410
print(f"Processing {input_file} with {max_workers} workers")
411
if enable_caching:
412
print("Caching enabled")
413
```