0
# Syntax Highlighting
1
2
Code syntax highlighting with theme support and extensive language coverage via Pygments. Rich provides comprehensive syntax highlighting capabilities for displaying source code with proper formatting and color schemes.
3
4
## Capabilities
5
6
### Syntax Class
7
8
Main syntax highlighting component with theme and formatting options.
9
10
```python { .api }
11
class Syntax:
12
"""
13
Syntax highlighted code display.
14
15
Args:
16
code: Source code to highlight
17
lexer: Pygments lexer name or instance
18
theme: Color theme name or SyntaxTheme instance
19
dedent: Remove common leading whitespace
20
line_numbers: Show line numbers
21
start_line: Starting line number
22
line_range: Range of lines to highlight (start, end)
23
highlight_lines: Set of line numbers to highlight
24
code_width: Fixed width for code or None for auto
25
tab_size: Size of tab characters in spaces
26
word_wrap: Enable word wrapping
27
background_color: Override background color
28
indent_guides: Show indentation guides
29
padding: Padding around code block
30
"""
31
def __init__(
32
self,
33
code: str,
34
lexer: Optional[Union[Lexer, str]] = None,
35
*,
36
theme: Union[str, SyntaxTheme] = "monokai",
37
dedent: bool = False,
38
line_numbers: bool = False,
39
start_line: int = 1,
40
line_range: Optional[Tuple[int, int]] = None,
41
highlight_lines: Optional[Set[int]] = None,
42
code_width: Optional[int] = None,
43
tab_size: int = 4,
44
word_wrap: bool = False,
45
background_color: Optional[str] = None,
46
indent_guides: bool = False,
47
padding: PaddingDimensions = 0,
48
): ...
49
50
@classmethod
51
def from_path(
52
cls,
53
path: Union[str, PathLike[str]],
54
encoding: str = "utf-8",
55
lexer: Optional[Union[Lexer, str]] = None,
56
theme: Union[str, SyntaxTheme] = "monokai",
57
dedent: bool = False,
58
line_numbers: bool = False,
59
line_range: Optional[Tuple[int, int]] = None,
60
start_line: int = 1,
61
highlight_lines: Optional[Set[int]] = None,
62
code_width: Optional[int] = None,
63
tab_size: int = 4,
64
word_wrap: bool = False,
65
background_color: Optional[str] = None,
66
indent_guides: bool = False,
67
padding: PaddingDimensions = 0,
68
) -> "Syntax":
69
"""
70
Create Syntax from file path.
71
72
Args:
73
path: Path to source code file
74
encoding: File encoding
75
lexer: Lexer name or None to auto-detect
76
theme: Syntax theme
77
dedent: Remove common indentation
78
line_numbers: Show line numbers
79
line_range: Range of lines to show
80
start_line: Starting line number
81
highlight_lines: Lines to highlight
82
code_width: Fixed code width
83
tab_size: Tab size in spaces
84
word_wrap: Enable word wrapping
85
background_color: Background color override
86
indent_guides: Show indentation guides
87
padding: Code block padding
88
89
Returns:
90
New Syntax instance with file contents
91
"""
92
93
@classmethod
94
def guess_lexer(cls, path: Union[str, PathLike[str]], code: str) -> str:
95
"""
96
Guess lexer from file path and content.
97
98
Args:
99
path: File path for extension hints
100
code: Source code content
101
102
Returns:
103
Lexer name for the code
104
"""
105
106
def highlight(self, code: str) -> Text:
107
"""
108
Apply syntax highlighting to code.
109
110
Args:
111
code: Source code to highlight
112
113
Returns:
114
Highlighted text object
115
"""
116
117
# Properties
118
@property
119
def lexer(self) -> Optional[Lexer]:
120
"""Get the Pygments lexer."""
121
122
@property
123
def theme(self) -> SyntaxTheme:
124
"""Get the syntax theme."""
125
```
126
127
### Syntax Themes
128
129
Theme system for syntax highlighting colors.
130
131
```python { .api }
132
class SyntaxTheme(ABC):
133
"""Abstract base for syntax highlighting themes."""
134
135
@abstractmethod
136
def get_style_for_token(self, token_type: TokenType) -> Style:
137
"""
138
Get style for a token type.
139
140
Args:
141
token_type: Pygments token type
142
143
Returns:
144
Rich Style for the token
145
"""
146
147
@abstractmethod
148
def get_background_style(self) -> Style:
149
"""
150
Get background style for code blocks.
151
152
Returns:
153
Rich Style for background
154
"""
155
156
class PygmentsSyntaxTheme(SyntaxTheme):
157
"""Syntax theme based on Pygments themes."""
158
159
def __init__(
160
self,
161
theme: Union[str, Type[PygmentsStyle]]
162
): ...
163
164
@classmethod
165
def get_theme_names(cls) -> List[str]:
166
"""
167
Get list of available Pygments theme names.
168
169
Returns:
170
List of theme names
171
"""
172
173
class ANSISyntaxTheme(SyntaxTheme):
174
"""Syntax theme using ANSI color codes."""
175
176
def __init__(self, style_map: Dict[TokenType, Style]): ...
177
178
# Default themes
179
DEFAULT_THEME: str # Default theme name
180
RICH_SYNTAX_THEMES: Dict[str, SyntaxTheme] # Available themes
181
```
182
183
**Usage Examples:**
184
185
```python
186
from rich.console import Console
187
from rich.syntax import Syntax
188
import tempfile
189
import os
190
191
console = Console()
192
193
# Basic syntax highlighting
194
python_code = '''
195
def fibonacci(n):
196
"""Generate Fibonacci sequence up to n."""
197
a, b = 0, 1
198
while a < n:
199
print(a, end=' ')
200
a, b = b, a + b
201
print()
202
203
fibonacci(100)
204
'''
205
206
syntax = Syntax(python_code, "python")
207
console.print(syntax)
208
209
# Syntax with line numbers
210
syntax = Syntax(
211
python_code,
212
"python",
213
line_numbers=True,
214
start_line=1
215
)
216
console.print(syntax)
217
218
# Highlight specific lines
219
syntax = Syntax(
220
python_code,
221
"python",
222
line_numbers=True,
223
highlight_lines={2, 4, 5} # Highlight lines 2, 4, and 5
224
)
225
console.print(syntax)
226
227
# Different themes
228
themes = ["monokai", "github-dark", "one-dark", "solarized-light"]
229
for theme in themes:
230
console.print(f"\n[bold]Theme: {theme}[/bold]")
231
syntax = Syntax(python_code, "python", theme=theme, line_numbers=True)
232
console.print(syntax)
233
234
# Load from file
235
# Create temporary file
236
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
237
f.write(python_code)
238
temp_path = f.name
239
240
try:
241
# Load and highlight from file
242
syntax = Syntax.from_path(
243
temp_path,
244
line_numbers=True,
245
theme="monokai"
246
)
247
console.print(syntax)
248
finally:
249
os.unlink(temp_path)
250
251
# JavaScript example
252
js_code = '''
253
function quickSort(arr) {
254
if (arr.length <= 1) {
255
return arr;
256
}
257
258
const pivot = arr[Math.floor(arr.length / 2)];
259
const left = arr.filter(x => x < pivot);
260
const middle = arr.filter(x => x === pivot);
261
const right = arr.filter(x => x > pivot);
262
263
return [...quickSort(left), ...middle, ...quickSort(right)];
264
}
265
266
const numbers = [64, 34, 25, 12, 22, 11, 90];
267
console.log(quickSort(numbers));
268
'''
269
270
syntax = Syntax(js_code, "javascript", theme="github-dark", line_numbers=True)
271
console.print(syntax)
272
273
# SQL example with custom settings
274
sql_code = '''
275
SELECT
276
customers.name,
277
orders.order_date,
278
products.product_name,
279
order_items.quantity * products.price AS total_price
280
FROM customers
281
JOIN orders ON customers.customer_id = orders.customer_id
282
JOIN order_items ON orders.order_id = order_items.order_id
283
JOIN products ON order_items.product_id = products.product_id
284
WHERE orders.order_date >= '2024-01-01'
285
ORDER BY orders.order_date DESC, total_price DESC;
286
'''
287
288
syntax = Syntax(
289
sql_code,
290
"sql",
291
theme="one-dark",
292
line_numbers=True,
293
word_wrap=True,
294
indent_guides=True
295
)
296
console.print(syntax)
297
298
# Show line range
299
long_code = '''
300
import os
301
import sys
302
import json
303
import requests
304
from datetime import datetime
305
from typing import List, Dict, Optional
306
307
class DataProcessor:
308
def __init__(self, config_path: str):
309
self.config = self.load_config(config_path)
310
self.session = requests.Session()
311
312
def load_config(self, path: str) -> Dict:
313
with open(path, 'r') as f:
314
return json.load(f)
315
316
def process_data(self, data: List[Dict]) -> List[Dict]:
317
results = []
318
for item in data:
319
processed = self.transform_item(item)
320
if self.validate_item(processed):
321
results.append(processed)
322
return results
323
324
def transform_item(self, item: Dict) -> Dict:
325
# Transform logic here
326
return {
327
'id': item.get('id'),
328
'timestamp': datetime.now().isoformat(),
329
'value': item.get('value', 0) * 2
330
}
331
332
def validate_item(self, item: Dict) -> bool:
333
return all(key in item for key in ['id', 'timestamp', 'value'])
334
'''
335
336
# Show only lines 10-20
337
syntax = Syntax(
338
long_code,
339
"python",
340
line_numbers=True,
341
line_range=(10, 20),
342
start_line=10,
343
theme="monokai"
344
)
345
console.print(syntax)
346
347
# Code with custom background
348
syntax = Syntax(
349
python_code,
350
"python",
351
theme="github-dark",
352
background_color="black",
353
padding=1
354
)
355
console.print(syntax)
356
357
# Dedent code (remove common indentation)
358
indented_code = '''
359
def helper_function():
360
print("This is indented")
361
return True
362
363
def another_function():
364
if helper_function():
365
print("Success!")
366
'''
367
368
syntax = Syntax(
369
indented_code,
370
"python",
371
dedent=True,
372
line_numbers=True
373
)
374
console.print(syntax)
375
376
# Auto-detect lexer from filename
377
def highlight_file_content(filename: str, content: str):
378
"""Highlight code with auto-detected lexer."""
379
lexer = Syntax.guess_lexer(filename, content)
380
syntax = Syntax(content, lexer, line_numbers=True)
381
console.print(f"[bold]File: {filename} (Lexer: {lexer})[/bold]")
382
console.print(syntax)
383
384
# Examples of auto-detection
385
highlight_file_content("script.py", "print('Hello, World!')")
386
highlight_file_content("style.css", "body { color: red; }")
387
highlight_file_content("config.json", '{"name": "example", "value": 42}')
388
389
# Syntax in panels
390
from rich.panel import Panel
391
392
code_panel = Panel(
393
Syntax(python_code, "python", theme="monokai"),
394
title="Python Code",
395
border_style="blue"
396
)
397
console.print(code_panel)
398
399
# Multiple code blocks in columns
400
from rich.columns import Columns
401
402
python_syntax = Syntax("print('Python')", "python", theme="github-dark")
403
js_syntax = Syntax("console.log('JavaScript');", "javascript", theme="github-dark")
404
405
columns = Columns([
406
Panel(python_syntax, title="Python"),
407
Panel(js_syntax, title="JavaScript")
408
])
409
console.print(columns)
410
```