This page covers the Syntax renderable in Rich, which produces syntax-highlighted code blocks in the terminal. It documents the Syntax class, its constructor and class methods, the SyntaxTheme hierarchy (PygmentsSyntaxTheme and ANSISyntaxTheme), lexer selection, and the stylize_range() API.
For general text highlighting with regex patterns (e.g., RegexHighlighter), see Themes and Customization. For how the Syntax class is used inside tracebacks, see Traceback Enhancement.
The Syntax class (rich/syntax.py240-314) wraps a string of source code and renders it as colored, terminal-compatible output by delegating tokenization to the Pygments library. It supports:
"monokai") as well as two built-in ANSI-safe themesstylize_range()Syntax implements __rich_console__ and __rich_measure__, making it a standard Rich renderable compatible with Console.print(), Panel, Columns, and other containers.
Sources: rich/syntax.py240-314 docs/source/syntax.rst1-57
Class hierarchy overview:
Sources: rich/syntax.py124-213 rich/syntax.py240-314
Syntax Class| Parameter | Type | Default | Description |
|---|---|---|---|
code | str | — | The source code to render |
lexer | Lexer | str | — | Pygments lexer instance or alias string (e.g. "python") |
theme | str | SyntaxTheme | "monokai" | Pygments style name or a SyntaxTheme instance |
dedent | bool | False | Strip common leading whitespace |
line_numbers | bool | False | Show line number gutter |
start_line | int | 1 | First line number shown |
line_range | Tuple[int|None, int|None] | None | Restrict rendering to a line range; None is open-ended |
highlight_lines | Set[int] | None | Line numbers to highlight with a pointer and bold number |
code_width | int | None | None | Fixed code column width; None uses available console width |
tab_size | int | 4 | Spaces per tab stop |
word_wrap | bool | False | Wrap long lines |
background_color | str | None | None | Override theme background (e.g. "red", "#282828") |
indent_guides | bool | False | Render vertical indent guide lines |
padding | PaddingDimensions | 0 | Padding around the block (top/right/bottom/left) |
The padding attribute is managed by the PaddingProperty descriptor (rich/syntax.py229-237) which unpacks values via Padding.unpack().
lexer PropertyWhen a string is passed as lexer, it is resolved lazily via get_lexer_by_name() from Pygments. If the name is not found, the property returns None and default_lexer (the plain-text "text" lexer) is used as a fallback.
A Pygments Lexer instance may also be passed directly, which bypasses name lookup entirely.
Sources: rich/syntax.py276-313 rich/syntax.py438-465
Syntax.from_path()A classmethod that reads the file at path, then calls guess_lexer() if no lexer argument is given. Accepts all the same keyword arguments as __init__.
syntax = Syntax.from_path("my_script.py", line_numbers=True, theme="monokai")
Syntax.guess_lexer()A classmethod that returns the string alias of the best Pygments lexer for a given path and optional code string.
Algorithm:
When both path and code are available (e.g. an HTML file containing Django template syntax), guess_lexer_for_filename from Pygments can return a compound lexer such as "html+django".
Sources: rich/syntax.py379-419 rich/syntax.py316-377
SyntaxTheme ABCThe abstract base class that all themes implement. It exposes two methods:
get_style_for_token(token_type: TokenType) -> Style — map a Pygments token tuple to a Rich Styleget_background_style() -> Style — return the background Style for the code blockPygmentsSyntaxThemeWraps any Pygments style class. Accepts a style name string or a PygmentsStyle subclass. Resolves styles from Pygments via style_for_token() and caches results in _style_cache. Falls back to "default" if the named theme is not installed.
The get_background_style() method returns Style(bgcolor=background_color) where background_color comes from the Pygments style class.
ANSISyntaxThemeUses a plain Dict[TokenType, Style] mapping, where styles use only standard ANSI color names. This means the output respects the terminal's own color theme rather than embedding specific RGB values.
Two built-in maps are defined at module level:
| Name | Constant | Description |
|---|---|---|
"ansi_dark" | ANSI_DARK | Bright color variants suited for dark terminals |
"ansi_light" | ANSI_LIGHT | Standard color variants suited for light terminals |
These are registered in RICH_SYNTAX_THEMES (rich/syntax.py120) and selected by get_theme() before falling through to PygmentsSyntaxTheme.
Style lookup walks the token hierarchy from most-specific to least-specific (e.g. Comment.Preproc → Comment → Token) until a match is found.
Syntax.get_theme()A classmethod that normalizes a str | SyntaxTheme value into a SyntaxTheme instance. If the string matches a key in RICH_SYNTAX_THEMES, an ANSISyntaxTheme is returned; otherwise a PygmentsSyntaxTheme is returned.
Theme resolution flow:
Sources: rich/syntax.py120-121 rich/syntax.py138-210 rich/syntax.py264-274
The Syntax object follows the standard Rich renderable protocol. When passed to console.print(), the console calls __rich_console__().
Rendering flow:
The _process_code() method (rich/syntax.py820-840) ensures the code string always ends with a newline and optionally applies textwrap.dedent().
The highlight() method (rich/syntax.py467-550) returns a Text object with per-token spans. When a line_range is given, it uses an optimized path that only stylizes the visible lines to reduce the number of Span objects.
When line_numbers=True, the gutter renders a line_pointer character ("❱ " on modern terminals, "> " on legacy Windows) next to highlighted lines.
Sources: rich/syntax.py640-785 rich/syntax.py467-550 rich/syntax.py820-840
stylize_range()Adds a _SyntaxHighlightRange entry to the internal _stylized_ranges list. These are applied on top of tokenization during highlight().
Signature:
stylize_range(
style: StyleType,
start: SyntaxPosition, # (line_number, column_index)
end: SyntaxPosition, # (line_number, column_index)
style_before: bool = False,
)
SyntaxPosition is Tuple[int, int] — line numbers are 1-based, column indexes are 0-based.style_before=True inserts the style under existing token styles; False (default) applies it on top.Internally, _apply_stylized_ranges() (rich/syntax.py787-818) maps SyntaxPosition values to flat character offsets in the Text object by pre-computing newline positions.
The Traceback renderer uses stylize_range() to underline the exact expression reported by CPython 3.11+ co_positions() data (rich/traceback.py880-884).
_SyntaxHighlightRange NamedTuple| Field | Type | Description |
|---|---|---|
style | StyleType | The style to apply |
start | SyntaxPosition | (line, col) start of range |
end | SyntaxPosition | (line, col) end of range |
style_before | bool | Apply before existing styles |
Sources: rich/syntax.py213-226 rich/syntax.py552-571 rich/syntax.py787-818 rich/traceback.py880-884
rich/syntax.py588-620 rich/syntax.py765-785
When line_numbers=True, a gutter column is prepended to each line. The width of the gutter is computed by _numbers_column_width based on the total number of lines in code.
highlight_lines receive a "❱ " prefix (or "> " on legacy Windows) in red and a bold, bright line number." " padding and a dim number style.On 256-color or truecolor terminals, the number color is computed by blending the background and foreground colors via blend_rgb() (rich/syntax.py573-586).
Sources: rich/syntax.py573-620 rich/syntax.py765-785
When indent_guides=True, Syntax calls Text.with_indent_guides() on the highlighted text before rendering. The guide style is constructed by combining the base theme style, the Comment token style, and Style(dim=True) (rich/syntax.py714-726). Indent guides are suppressed automatically when options.ascii_only is set (e.g., on terminals that do not support Unicode box-drawing characters).
Sources: rich/syntax.py714-726 rich/syntax.py685-688
The Traceback class (rich/traceback.py262-895) creates Syntax instances for each stack frame:
On Python 3.11+, stylize_range() is then called to underline the specific sub-expression that caused the error, based on frame.last_instruction data from co_positions().
Traceback also uses Syntax.get_theme() to resolve a SyntaxTheme once at construction time and shares it across all frames (rich/traceback.py328).
Sources: rich/traceback.py842-895 rich/traceback.py328
rich/syntax.py includes a __main__ block so the class can be used directly from the command line:
python -m rich.syntax syntax.py
python -m rich.syntax -h
This prints the file with auto-detected lexer, line numbers, and the default "monokai" theme.
Sources: docs/source/syntax.rst47-57
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.