0
# Styling and Formatting
1
2
The styling and formatting system provides rich text output capabilities including colors, text formatting options, and custom styles. It enables creating visually appealing CLI output with consistent styling and theming support.
3
4
## Capabilities
5
6
### Formatter Class
7
8
The main formatting engine that processes styled text with embedded tags and applies formatting.
9
10
```python { .api }
11
class Formatter:
12
def __init__(self, decorated: bool = False, styles: dict[str, Style] | None = None) -> None:
13
"""
14
Create a text formatter.
15
16
Args:
17
decorated (bool): Whether to enable color/formatting output
18
styles (dict[str, Style] | None): Predefined styles dictionary
19
"""
20
21
def format(self, message: str) -> str:
22
"""
23
Format a message with embedded style tags.
24
25
Args:
26
message (str): Message with style tags like <info>text</info>
27
28
Returns:
29
str: Formatted message with ANSI codes or plain text
30
"""
31
32
def set_style(self, name: str, style: Style) -> None:
33
"""
34
Register a named style.
35
36
Args:
37
name (str): Style name for tag usage
38
style (Style): Style configuration
39
"""
40
41
def has_style(self, name: str) -> bool:
42
"""
43
Check if a style is registered.
44
45
Args:
46
name (str): Style name to check
47
48
Returns:
49
bool: True if style exists
50
"""
51
52
def get_style(self, name: str) -> Style:
53
"""
54
Get a registered style by name.
55
56
Args:
57
name (str): Style name
58
59
Returns:
60
Style: The style configuration
61
"""
62
63
def is_decorated(self) -> bool:
64
"""
65
Check if formatter produces decorated output.
66
67
Returns:
68
bool: True if decoration is enabled
69
"""
70
71
def decorated(self, decorated: bool = True) -> None:
72
"""
73
Enable or disable output decoration.
74
75
Args:
76
decorated (bool): Whether to enable decoration
77
"""
78
```
79
80
### Style Class
81
82
Individual style configuration for text formatting including colors and text effects.
83
84
```python { .api }
85
class Style:
86
def __init__(self, foreground: str | None = None, background: str | None = None,
87
options: list[str] | None = None) -> None:
88
"""
89
Create a text style.
90
91
Args:
92
foreground (str | None): Foreground color name
93
background (str | None): Background color name
94
options (list[str] | None): Formatting options (bold, italic, etc.)
95
"""
96
97
def foreground(self, foreground: str) -> Style:
98
"""
99
Set foreground color and return new style.
100
101
Args:
102
foreground (str): Color name
103
104
Returns:
105
Style: New style with foreground color
106
"""
107
108
def background(self, background: str) -> Style:
109
"""
110
Set background color and return new style.
111
112
Args:
113
background (str): Color name
114
115
Returns:
116
Style: New style with background color
117
"""
118
119
def bold(self, bold: bool = True) -> Style:
120
"""
121
Set bold formatting and return new style.
122
123
Args:
124
bold (bool): Whether to enable bold
125
126
Returns:
127
Style: New style with bold formatting
128
"""
129
130
def italic(self, italic: bool = True) -> Style:
131
"""
132
Set italic formatting and return new style.
133
134
Args:
135
italic (bool): Whether to enable italic
136
137
Returns:
138
Style: New style with italic formatting
139
"""
140
141
def underline(self, underline: bool = True) -> Style:
142
"""
143
Set underline formatting and return new style.
144
145
Args:
146
underline (bool): Whether to enable underline
147
148
Returns:
149
Style: New style with underline formatting
150
"""
151
152
def blink(self, blink: bool = True) -> Style:
153
"""
154
Set blink formatting and return new style.
155
156
Args:
157
blink (bool): Whether to enable blink
158
159
Returns:
160
Style: New style with blink formatting
161
"""
162
163
def reverse(self, reverse: bool = True) -> Style:
164
"""
165
Set reverse formatting and return new style.
166
167
Args:
168
reverse (bool): Whether to enable reverse
169
170
Returns:
171
Style: New style with reverse formatting
172
"""
173
174
def conceal(self, conceal: bool = True) -> Style:
175
"""
176
Set conceal formatting and return new style.
177
178
Args:
179
conceal (bool): Whether to enable conceal
180
181
Returns:
182
Style: New style with conceal formatting
183
"""
184
185
def apply(self, text: str) -> str:
186
"""
187
Apply this style to text.
188
189
Args:
190
text (str): Text to style
191
192
Returns:
193
str: Styled text with ANSI codes
194
"""
195
```
196
197
### Color Class
198
199
Low-level color and formatting code generation for terminal output.
200
201
```python { .api }
202
class Color:
203
COLORS: ClassVar[dict[str, tuple[int, int]]] = {
204
'black': (30, 40),
205
'red': (31, 41),
206
'green': (32, 42),
207
'yellow': (33, 43),
208
'blue': (34, 44),
209
'magenta': (35, 45),
210
'cyan': (36, 46),
211
'white': (37, 47),
212
'default': (39, 49)
213
}
214
215
AVAILABLE_OPTIONS: ClassVar[dict[str, dict[str, int]]] = {
216
'bold': {'set': 1, 'unset': 22},
217
'underscore': {'set': 4, 'unset': 24},
218
'blink': {'set': 5, 'unset': 25},
219
'reverse': {'set': 7, 'unset': 27},
220
'conceal': {'set': 8, 'unset': 28}
221
}
222
223
def __init__(self, foreground: str = "", background: str = "",
224
options: list[str] | None = None) -> None:
225
"""
226
Create a color configuration.
227
228
Args:
229
foreground (str): Foreground color name
230
background (str): Background color name
231
options (list[str] | None): Formatting options
232
"""
233
234
def apply(self, text: str) -> str:
235
"""
236
Apply color and formatting to text.
237
238
Args:
239
text (str): Text to colorize
240
241
Returns:
242
str: Text with ANSI escape codes
243
"""
244
245
def set(self) -> str:
246
"""
247
Get ANSI codes to enable this color/formatting.
248
249
Returns:
250
str: ANSI escape sequence to set formatting
251
"""
252
253
def unset(self) -> str:
254
"""
255
Get ANSI codes to disable this color/formatting.
256
257
Returns:
258
str: ANSI escape sequence to unset formatting
259
"""
260
```
261
262
## Predefined Styles
263
264
Cleo includes several predefined styles for common use cases:
265
266
### Built-in Style Tags
267
268
```python { .api }
269
# Predefined styles available in formatters
270
PREDEFINED_STYLES = {
271
'error': Style('red'), # Red text for errors
272
'info': Style('blue'), # Blue text for information
273
'comment': Style('green'), # Green text for comments
274
'question': Style('cyan'), # Cyan text for questions
275
'warning': Style('yellow'), # Yellow text for warnings
276
}
277
```
278
279
## Usage Examples
280
281
### Basic Text Styling
282
283
```python
284
from cleo.formatters.formatter import Formatter
285
from cleo.formatters.style import Style
286
287
# Create formatter
288
formatter = Formatter(decorated=True)
289
290
# Use predefined styles with tags
291
message = formatter.format("<info>Processing complete</info>")
292
error = formatter.format("<error>File not found</error>")
293
comment = formatter.format("<comment>This is a comment</comment>")
294
295
# Inline color specifications
296
colored = formatter.format("<fg=red>Red text</fg>")
297
background = formatter.format("<bg=yellow>Yellow background</>")
298
combined = formatter.format("<fg=white;bg=blue;options=bold>Bold white on blue</>")
299
```
300
301
### Custom Style Creation
302
303
```python
304
# Create custom styles
305
success_style = Style('green').bold()
306
warning_style = Style('yellow').background('black')
307
debug_style = Style('cyan').italic()
308
309
# Register custom styles
310
formatter.set_style('success', success_style)
311
formatter.set_style('warning', warning_style)
312
formatter.set_style('debug', debug_style)
313
314
# Use custom styles
315
output = formatter.format("<success>Operation successful!</success>")
316
warning = formatter.format("<warning>Deprecated feature used</warning>")
317
debug = formatter.format("<debug>Debug information here</debug>")
318
```
319
320
### Style Chaining and Combination
321
322
```python
323
# Chain style methods for complex formatting
324
fancy_style = (Style()
325
.foreground('white')
326
.background('blue')
327
.bold()
328
.underline())
329
330
# Apply style directly to text
331
styled_text = fancy_style.apply("Important Message")
332
333
# Use with formatter
334
formatter.set_style('fancy', fancy_style)
335
message = formatter.format("<fancy>This is fancy text</fancy>")
336
```
337
338
### Command Output Styling
339
340
```python
341
# In a command class
342
class DeployCommand(Command):
343
def handle(self):
344
# Success messages
345
self.line("<info>Starting deployment...</info>")
346
347
# Warnings
348
self.line("<comment>Warning: This will overwrite existing files</comment>")
349
350
# Errors
351
self.line("<error>Deployment failed: Connection timeout</error>")
352
353
# Custom inline styling
354
self.line("<fg=green;options=bold>✓ All tests passed</>")
355
self.line("<bg=red;fg=white> ERROR </> Critical failure occurred")
356
357
# Add custom style for this command
358
self.add_style('highlight', fg='yellow', bg='black', options=['bold'])
359
self.line("<highlight>Key information highlighted</highlight>")
360
```
361
362
### Conditional Styling
363
364
```python
365
class StatusCommand(Command):
366
def handle(self):
367
status = self.get_system_status()
368
369
# Style based on status
370
if status == 'healthy':
371
self.line("<info>System Status: Healthy</info>")
372
elif status == 'warning':
373
self.line("<comment>System Status: Warning</comment>")
374
else:
375
self.line("<error>System Status: Critical</error>")
376
377
# Progress indicators with styling
378
for i in range(5):
379
if i < 3:
380
self.line(f"<info>✓</info> Service {i+1}: Running")
381
else:
382
self.line(f"<error>✗</error> Service {i+1}: Stopped")
383
```
384
385
### Table and List Styling
386
387
```python
388
class ReportCommand(Command):
389
def handle(self):
390
# Styled table headers and data
391
table = self.table()
392
table.set_headers([
393
'<info>Service</info>',
394
'<comment>Status</comment>',
395
'<question>Uptime</question>'
396
])
397
398
table.add_rows([
399
['Web Server', '<info>Running</info>', '5 days'],
400
['Database', '<error>Stopped</error>', '0 minutes'],
401
['Cache', '<comment>Warning</comment>', '2 hours']
402
])
403
404
table.render()
405
406
# Styled lists
407
self.line("\n<info>Available Commands:</info>")
408
commands = ['start', 'stop', 'restart', 'status']
409
for cmd in commands:
410
self.line(f" <comment>•</comment> {cmd}")
411
```
412
413
### Environment-Specific Styling
414
415
```python
416
def create_environment_formatter(env: str) -> Formatter:
417
"""Create formatter with environment-specific styles."""
418
formatter = Formatter(decorated=True)
419
420
if env == 'development':
421
formatter.set_style('env', Style('green').bold())
422
elif env == 'staging':
423
formatter.set_style('env', Style('yellow').bold())
424
elif env == 'production':
425
formatter.set_style('env', Style('red').bold())
426
427
return formatter
428
429
# Usage
430
formatter = create_environment_formatter('production')
431
message = formatter.format(f"<env>PRODUCTION</env> deployment initiated")
432
```