rich-rst - Man Page
Name
rich-rst — rich-rst
rich-rst is a reStructuredText <https://docutils.sourceforge.io/rst.html> renderer for the Rich <https://rich.readthedocs.io/en/latest/> library. It lets you render RST documents beautifully in the terminal, with full support for headings, code blocks, tables, admonitions, footnotes, and all rst elements. A kitchen sink style rendering reference can be viewed in Sphinx & RST Demo Gallery <>
Installation
Install the latest stable release from PyPI:
python -m pip install rich-rst
To install the development version directly from the main branch:
python -m pip install "git+https://github.com/wasi-master/rich-rst"
- Note:
On Linux and macOS you may need to use python3 instead of python. On Windows you can use py as a shorthand.
Quick Start
Pass any RST string to RestructuredText and print it with Rich:
from rich import print
from rich_rst import RestructuredText
print(RestructuredText("Hello *World!*"))For a full list of constructor parameters see the API reference <>.
Command-Line Interface
Render a file directly from the terminal:
python -m rich_rst README.rst
Read from standard input:
cat README.rst | python -m rich_rst -
Run python -m rich_rst --help for the full list of options.
Contributing
rich-rst is open source. The source code <https://github.com/wasi-master/rich-rst> is hosted on GitHub. Bug reports and pull requests are welcome on the issue tracker <https://github.com/wasi-master/rich-rst/issues>.
API Reference
Python API
For visitor- and plugin-style customization, see Extension API <>.
The main class is RestructuredText. Several aliases are provided for convenience; they are identical:
| Name | Import path |
| RestructuredText | from rich_rst import RestructuredText |
| ReStructuredText | from rich_rst import ReStructuredText |
| reStructuredText | from rich_rst import reStructuredText |
| RST | from rich_rst import RST |
| reST | from rich_rst import reST |
Command-line interface
rich-rst ships with a CLI module that renders RST files (or stdin) directly to the terminal.
Usage
python -m rich_rst PATH [options] python -m rich_rst - [options] # read from stdin
PATH is required unless you use --list-html-themes.
Options
| Flag | Description |
| -c, --force-color | Force ANSI colour output even on non-terminal streams. |
| -d, --debug | Enable debug logging to help troubleshoot issues. |
| --version | Show the installed package version and exit. |
| -e, --encoding | File encoding (default: utf-8). |
| -w, --width | Output width in columns (auto-detected by default). |
| -hw, --html-width | max-width applied when saving HTML output (default: 1675px). |
| -t, --code-theme | Pygments theme used for syntax-highlighted code blocks (default: monokai). |
| --show-line-numbers | Show line numbers in syntax-highlighted code blocks. |
| -S, --save-html | Path to save the rendered output as an HTML file. |
| -r, --wrap | Hard-wrap long lines. |
| -s, --soft-wrap | Enable soft-wrap mode (lines are wrapped by the terminal). |
| -gl, --guess-lexer | Guess the syntax-highlighting language for code blocks that do not specify one. |
| -dl, --default-lexer | Fallback language for code blocks when none is detected (default: python). |
| -se, --show-errors | Show RST parse errors and warnings. |
| --admonition-style | How to render admonitions (panel or compact, default: panel). |
| --html-theme | Theme for --save-html output. Available values: dracula, monokai, night-owl, dimmed-monokai, default. |
| --list-html-themes | Print available HTML themes and exit. |
| -o, --output | Write rendered plain-text output to a file instead of stdout. |
Sphinx & RST Demo Gallery
This page shows every supported RST and Sphinx element rendered by rich-rst. For each element the raw RST source is shown in a code block, followed by the terminal-styled HTML snapshot produced by rich-rst (Dracula theme, 76-column width).
On this page
Inline Markup
- Emphasis (italic)
- Strong (bold)
- Inline literal (code)
- Hyperlink (external)
- Anonymous hyperlink
- Title reference
- Subscript role
- Superscript role
- Abbreviation role
- Keyboard role
- GUI label role
- Menu selection role
- File role
- Sample (samp) role
- Command role
- Program role
- All inline styles combined
- Inline markup in a list
- PEP reference role
- RFC reference role
- Definition (dfn) role
- CVE reference role
- CWE reference role
- PyPI project reference role
- Math role (inline)
Paragraphs and Sections
- Plain paragraph
- Section headings (all 6 levels)
- Section with overline decoration
- Document subtitle
- Multiple paragraphs with transitions
Lists
- Bullet list (dash)
- Bullet list (asterisk)
- Nested bullet list
- Enumerated list (auto-numbered)
- Bullet list (plus sign)
- Deeply nested bullet list
- Enumerated list (uppercase letters)
- Enumerated list (uppercase roman numerals)
- Mixed ordered and unordered lists
- Enumerated list (letters)
- Enumerated list (roman numerals)
- Definition list
- Definition list with classifier
- Field list
- Option list
- Horizontal list (hlist)
Block Markup
- Block quote
- Line block
- Doctest block
- Literal block (indented)
- Compound directive
- Parsed literal block
- Epigraph directive
- Highlights directive
- Pull-quote directive
Code Blocks
- code-block with language
- code-block with line numbers
- code-block with lineno-start
- code-block with emphasize-lines
- code-block with name
- code-block with dedent
- code-block: bash
- code-block: JSON
- code-block: YAML
- sourcecode alias
- code alias (no language)
- code-block: C
- code-block: Java
- code-block: TypeScript
- code-block: SQL
- code-block: HTML
- code-block: Rust
- code-block with caption
- productionlist directive
Admonitions
- note
- warning
- tip
- important
- hint
- attention
- caution
- danger
- error
- Admonition with bold content (box-char rendering test)
- Note with code and emphasis
- Generic admonition with custom title
- Admonition with nested content
Tables
- Simple table with header
- Grid table with row spanning
- Wider grid table
- list-table directive
- CSV Table
- Flat Table: Basic with Stub Column
- Flat Table: Column Span (:cspan:)
- Flat Table: Row Span (:rspan:)
- Flat Table: Combined :cspan: and :rspan:
- flat-table — single cell with :cspan: and :rspan: (2×2 block)
- flat-table — :cspan: fills merged column width without inflation
Footnotes and Citations
- Manual footnote
- Auto-numbered footnote
- Named auto footnote
- Symbol footnote
- Citation
Hyperlinks and Targets
- Standalone hyperlink
- External hyperlink (named)
- Internal cross-reference (indirect target)
- Anonymous hyperlink
Substitutions
- Text substitution
- Date substitution
- Unicode substitution
- Image substitution
Images and Figures
- image directive
- figure directive
- figure with legend
Document Structure Directives
- topic directive
- sidebar directive
- rubric directive
- contents directive (table of contents)
- sectnum directive
- header directive
- footer directive
- centered directive
Math
- Inline math role
- math directive (display)
- math directive (labeled)
Document Info (docinfo)
- Standard docinfo fields
- Authors list
Comments
- RST comment (invisible)
Raw Directive
- raw html directive
- raw latex directive
Sphinx Version Directives
- versionadded
- versionchanged
- deprecated
- deprecated-removed
Sphinx Cross-Reference Roles
- :func: role
- :class: role
- :meth: role
- :attr: role
- :mod: role
- :exc: role
- :obj: role
- :data: role
- :const: role
- :term: role
- :ref: role (cross-reference)
- :doc: role
- :envvar: role
Python Domain Directives
- py:function
- py:class
- py:method
- py:attribute
- py:data
- py:exception
- py:module
- py:decorator
See Also
- seealso directive
Toctree (Sphinx)
- toctree directive
- toctree with numbered entries
Glossary
- glossary directive
- glossary (sorted)
Mixed Sphinx Roles in Prose
- Mixed roles in a paragraph
Inline Markup
Emphasis (italic)
*italicised text*
Strong (bold)
**bold text**
Inline literal (code)
Use ``print()`` to display output.
Hyperlink (external)
Visit `Python <https://www.python.org>`_ for more.
Anonymous hyperlink
See `Rich docs <https://rich.readthedocs.io>`__ for styling.
Title reference
Read `The Zen of Python` for inspiration.
Subscript role
H\ :sub:`2`\ O is water.
Superscript role
E = mc\ :sup:`2`
Abbreviation role
:abbr:`RST (reStructuredText)` is a markup language.
Keyboard role
Press :kbd:`Ctrl+C` to copy.
GUI label role
Click :guilabel:`OK` to confirm.
Menu selection role
Go to :menuselection:`File --> Save As`.
File role
Edit :file:`/etc/hosts` with sudo.
Sample (samp) role
Type :samp:`ping {host}` in the terminal.Command role
Run :command:`python -m pytest`.
Program role
:program:`git` is a distributed version control system.
All inline styles combined
*Italic*, **bold**, ``literal``, :kbd:`Ctrl+C`, :guilabel:`OK`, :menuselection:`File --> Open`, :file:`~/.bashrc`, :command:`ls -la`, and :sup:`superscript`.
Inline markup in a list
- Use **bold** for important terms - Use *italic* for emphasis - Use ``code`` for inline code samples - Use :kbd:`Enter` for key presses
PEP reference role
See :pep:`8` for Python style guidelines.
RFC reference role
HTTP is described in :rfc:`2616`.
Definition (dfn) role
A :dfn:`docstring` is a string literal that documents a Python object.
CVE reference role
This vulnerability is tracked as :cve:`2024-3094`.
CWE reference role
This bug is categorized under :cwe:`79`.
PyPI project reference role
Install the package from :pypi:`requests`.
Math role (inline)
The area of a circle is :math:`\pi r^2`.
Paragraphs and Sections
Plain paragraph
This is a plain paragraph. Paragraphs are separated by blank lines. A second paragraph follows here.
Section headings (all 6 levels)
Level 1 Title ============= Some body text under level 1. Level 2 Title ------------- Some body text under level 2. Level 3 Title ~~~~~~~~~~~~~ Some body text under level 3. Level 4 Title ^^^^^^^^^^^^^ Some body text under level 4. Level 5 Title """"""""""""" Some body text under level 5. Level 6 Title ''''''''''''' Some body text under level 6.
Section with overline decoration
################## Part-level heading ################## Body text below the overlined heading.
Document subtitle
My Document =========== A subtitle here --------------- Body text.
Multiple paragraphs with transitions
First paragraph before the transition. ---- Second paragraph after the first transition. ---- Third paragraph after the second transition.
Lists
Bullet list (dash)
- First item - Second item - Third item
Bullet list (asterisk)
* Alpha * Beta * Gamma
Nested bullet list
- Parent item - Child item one - Child item two - Another parent
Enumerated list (auto-numbered)
#. First step #. Second step #. Third step
Bullet list (plus sign)
+ One + Two + Three
Deeply nested bullet list
- Level 1 item A
- Level 2 item A1
- Level 3 item A1a
- Level 3 item A1b
- Level 2 item A2
- Level 1 item BEnumerated list (uppercase letters)
A. Alpha B. Beta C. Gamma
Enumerated list (uppercase roman numerals)
I. Chapter One II. Chapter Two III. Chapter Three
Mixed ordered and unordered lists
Steps to install: 1. Download the package - Linux: ``apt install ...`` - macOS: ``brew install ...`` 2. Run the installer 3. Verify with ``--version``
Enumerated list (letters)
a. Apple b. Banana c. Cherry
Enumerated list (roman numerals)
i. Item i ii. Item ii iii. Item iii
Definition list
term
Definition of the term.
another term
Its definition spans
multiple lines.Definition list with classifier
term : string
A string-typed term.
count : int
An integer count.Field list
:Name: John Doe :Email: john@example.com :Role: Developer
Option list
-v, --verbose Enable verbose output. -o FILE Write output to FILE. --help Show this help message.
Horizontal list (hlist)
.. hlist:: :columns: 3 * Alpha * Beta * Gamma * Delta * Epsilon * Zeta
Block Markup
Block quote
Normal paragraph.
This is an indented block quote.
-- AttributionLine block
| The first line of a poem. | The second line continues. | An indented third line.
Doctest block
>>> print("Hello, world!")
Hello, world!
>>> 1 + 1
2Literal block (indented)
Example code::
def greet(name):
print(f"Hello, {name}!")Compound directive
.. compound:: The first sentence of a paragraph. The second paragraph of the compound block, rendered as a single logical paragraph.
Parsed literal block
.. parsed-literal:: **Bold** and *italic* inside a literal block. Also ``code`` here.
Epigraph directive
.. epigraph:: No man is an island, entire of itself. -- John Donne
Highlights directive
.. highlights:: Key takeaways: - Keep it simple. - Document everything.
Pull-quote directive
.. pull-quote:: The best way to predict the future is to invent it. -- Alan Kay
Code Blocks
code-block with language
.. code-block:: python
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)code-block with line numbers
.. code-block:: python :linenos: x = 1 y = 2 print(x + y)
code-block with lineno-start
.. code-block:: python :linenos: :lineno-start: 10 x = 1 y = 2
code-block with emphasize-lines
.. code-block:: python
:emphasize-lines: 3,5
def some_function():
interesting = False
print('This line is highlighted.')
print('This one is not...')
print('...but this one is.')code-block with name
.. code-block:: python :name: example-id x = 1 y = 2
code-block with dedent
.. code-block:: python
:dedent:
def foo():
return 1code-block: bash
.. code-block:: bash pip install rich-rst python -m rich_rst README.rst
code-block: JSON
.. code-block:: json
{
"name": "rich-rst",
"version": "1.0.0",
"description": "RST renderer for Rich"
}code-block: YAML
.. code-block:: yaml
name: rich-rst
dependencies:
- rich>=10.0
- docutils>=0.17sourcecode alias
.. sourcecode:: javascript
const greet = (name) => `Hello, ${name}!`;
console.log(greet('World'));code alias (no language)
.. code:: plain text block no syntax highlighting
code-block: C
.. code-block:: c
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
}code-block: Java
.. code-block:: java
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}code-block: TypeScript
.. code-block:: typescript
function greet(name: string): string {
return `Hello, ${name}!`;
}
console.log(greet("World"));code-block: SQL
.. code-block:: sql SELECT name, email FROM users WHERE active = TRUE ORDER BY name ASC LIMIT 10;
code-block: HTML
.. code-block:: html
<!doctype html>
<html lang="en">
<head><title>Hello</title></head>
<body><h1>Hello, World!</h1></body>
</html>code-block: Rust
.. code-block:: rust
fn main() {
let greeting = "Hello, World!";
println!("{}", greeting);
}code-block with caption
.. code-block:: python
:caption: example.py
def add(a, b):
# This line is emphasised
return a + bproductionlist directive
.. productionlist::
statement : expression NEWLINE
expression : term ('+' term)*
term : factor ('*' factor)*Admonitions
note
.. note:: This is a note admonition.
warning
.. warning:: This is a warning.
tip
.. tip:: This is a tip.
important
.. important:: This is important.
hint
.. hint:: This is a hint.
attention
.. attention:: Pay attention to this.
caution
.. caution:: Exercise caution here.
danger
.. danger:: Danger! Proceed carefully.
error
.. error:: An error occurred.
Admonition with bold content (box-char rendering test)
.. warning:: **Never** commit secrets to version control. Use environment variables or a secrets manager instead.
Note with code and emphasis
.. note:: Call ``sys.exit(0)`` to terminate *successfully*, or ``sys.exit(1)`` for **failure**.
Generic admonition with custom title
.. admonition:: Did you know? rich-rst supports all currently documented RST elements.
Admonition with nested content
.. note:: Notes can contain **bold**, *italic*, and ``code``. They can also contain lists: - item one - item two
Tables
Simple table with header
===== ===== ====== Col A Col B Col C ===== ===== ====== 1 2 3 4 5 6 ===== ===== ======
Grid table with row spanning
+------------+------------+ | Column 1 | Column 2 | +============+============+ | Rows 1 & 2 | Row 1 | + +------------+ | | Row 2 | +------------+------------+
Wider grid table
+--------+-------+------+---------+ | Name | Type | Size | Default | +========+=======+======+=========+ | width | int | 4 | 80 | +--------+-------+------+---------+ | height | int | 4 | 24 | +--------+-------+------+---------+ | title | str | var | '' | +--------+-------+------+---------+
list-table directive
.. list-table:: Comparison
:header-rows: 1
:widths: 30 35 35
* - Library
- Language
- Stars
* - rich
- Python
- 50k+
* - rich-rst
- Python
- 1k+CSV Table
.. csv-table:: Data :header: "Name", "Value", "Unit" :widths: 20, 20, 20 "Speed", "299 792 458", "m/s" "Charge", "1.602e-19", "C" "Mass", "9.109e-31", "kg"
Flat Table: Basic with Stub Column
.. flat-table:: Linux Kernel Subsystems
:header-rows: 1
:stub-columns: 1
* - Subsystem
- Maintainer
- Description
* - Networking
- David S. Miller
- TCP/IP stack and network drivers
* - Memory Management
- Andrew Morton
- Virtual memory, paging, and allocators
* - File Systems
- Linus Torvalds
- VFS layer and filesystem driversFlat Table: Column Span (:cspan:)
.. flat-table:: Quarterly Results
:header-rows: 1
* - Student
- Q1
- Q2
- Q3
* - :cspan:`3` Grand total — all students, all quarters
* - Alice
- 90
- 85
- 92
* - Bob
- 80
- 88
- 76Flat Table: Row Span (:rspan:)
.. flat-table:: Produce Prices
:header-rows: 1
* - Category
- Item
- Price
* - :rspan:`1` Fruit
- Apple
- $1.00
* - Banana
- $0.50
* - :rspan:`1` Vegetable
- Carrot
- $0.75
* - Broccoli
- $1.25Flat Table: Combined :cspan: and :rspan
.. flat-table:: Combined Spans
:header-rows: 3
* - Full-width title header
* - :cspan:`1` header 1
- :cspan:`1` header 2
- :cspan:`1` header 3
* - Sub-header 1
- Sub-header 2
- Sub-header 3
- Sub-header 4
- Sub-header 5
- Sub-header 6
* - :rspan:`1` :cspan:`1` Big cell spanning 2 rows and 2 column
- :cspan:`1` Large cell spanning 2 columns
- :cspan:`3` Large cell spanning 4 columns
* - :rspan:`1` Tall cell spanning 2 rows
- Cell 3
- :rspan:`1` :cspan:`2` Big cell spanning 2 rows and 3 columns
* - Cell 1
- Cell 2
- Cell 4
-flat-table — single cell with :cspan: and :rspan: (2×2 block)
.. flat-table:: 2×2 merged cell
:header-rows: 1
* - Task
- Mon
- Tue
- Wed
- Thu
- Fri
* - :cspan:`2` :rspan:`1` Planning
- Review
* - Deploy
* - Others.flat-table — :cspan: fills merged column width without inflation
.. flat-table:: Team Overview
:header-rows: 1
* - Name
- Role
* - :cspan:`1` Both columns
* - Alice
- Lead
* - Bob
- DevFootnotes and Citations
Manual footnote
See the footnote [1]_ for details. .. [1] This is the footnote text.
Auto-numbered footnote
First reference [#]_. Second reference [#]_. .. [#] First auto footnote. .. [#] Second auto footnote.
Named auto footnote
See [#note]_ for details. .. [#note] The named auto footnote.
Symbol footnote
Marked with a symbol [*]_. .. [*] Symbol footnote text.
Citation
As described in [Doe2023]_. .. [Doe2023] John Doe. *Python Patterns*. 2023.
Hyperlinks and Targets
Standalone hyperlink
Visit https://python.org for more.
External hyperlink (named)
Read the `Rich documentation`_. .. _Rich documentation: https://rich.readthedocs.io
Internal cross-reference (indirect target)
Jump to `Target Section`_. Target Section ~~~~~~~~~~~~~~ Content here.
Anonymous hyperlink
See `this page <https://example.com>`__ for details.
Substitutions
Text substitution
|project| is written in Python. .. |project| replace:: rich-rst
Date substitution
Generated on |today|. .. |today| date:: %Y-%m-%d
Unicode substitution
Copyright |copy| 2024 The Authors. .. |copy| unicode:: U+00A9 .. copyright sign
Image substitution
Click the |logo| icon. .. |logo| image:: https://example.com/logo.png :alt: Logo
Images and Figures
image directive
.. image:: https://example.com/photo.png :alt: A photo :width: 400px
figure directive
.. figure:: https://example.com/chart.png :alt: A chart :width: 600px Figure caption goes here.
figure with legend
.. figure:: https://example.com/diagram.png :alt: Diagram Caption text. Legend text with more details about the figure.
Document Structure Directives
topic directive
.. topic:: Interesting Fact This is the topic body. It can contain any body elements.
rubric directive
.. rubric:: An Unnumbered Heading Following paragraph.
contents directive (table of contents)
.. contents:: Table of Contents :depth: 2 Section A --------- Content A. Section B --------- Content B.
sectnum directive
.. sectnum:: Overview -------- Details -------
header directive
.. header:: My Document Header Main content.
centered directive
.. centered:: IMPORTANT NOTICE Body text.
Math
Inline math role
The Pythagorean theorem: :math:`a^2 + b^2 = c^2`.
math directive (display)
.. math::
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}math directive (labeled)
.. math:: E = mc^2 :label: einstein
Document Info (docinfo)
Standard docinfo fields
My Report ========= :Author: Jane Smith :Date: 2024-01-15 :Version: 1.0 :Status: Draft :Copyright: 2024 Jane Smith :Organization: ACME Corp Body of the document.
Authors list
:Authors: - Alice
- Bob
- Carol
Body text.Comments
RST comment (invisible)
Before comment. .. This is an RST comment and should not appear in output. After comment.
Raw Directive
raw html directive
.. raw:: html <strong>Bold via raw HTML</strong>
raw latex directive
.. raw:: latex
\textbf{Bold via LaTeX}Sphinx Version Directives
versionadded
.. versionadded:: 2.1 This feature was added in version 2.1.
versionchanged
.. versionchanged:: 3.0 The API changed in version 3.0.
deprecated
.. deprecated:: 1.5 Use the new API instead.
deprecated-removed
.. deprecated-removed:: 1.5 2.0 Removed in 2.0. Use the new API.
Sphinx Cross-Reference Roles
func: role
Call :func:`os.path.join` to join paths.
class: role
Use :class:`pathlib.Path` for path handling.
meth: role
Call :meth:`str.upper` to uppercase a string.
attr: role
Access :attr:`os.sep` for the path separator.
mod: role
The :mod:`os.path` module provides path utilities.
exc: role
Raises :exc:`ValueError` when the input is invalid.
obj: role
Set :obj:`sys.path` to control module lookup.
data: role
Read :data:`sys.version` for the Python version.
const: role
The value of :const:`math.pi` is approximately 3.14.
term: role
A :term:`decorator` wraps another function.
ref: role (cross-reference)
See :ref:`some-label` for details.
doc: role
Refer to :doc:`installation` for setup instructions.
envvar: role
Set :envvar:`PYTHONPATH` before running.
Python Domain Directives
py:function
.. py:function:: greet(name: str) -> str Return a greeting for *name*. :param name: The name to greet. :type name: str :returns: A greeting string. :rtype: str
py:class
.. py:class:: MyClass(value) A simple example class. :param value: Initial value. :type value: int
py:method
.. py:method:: MyClass.process(data) Process the given *data*.
py:attribute
.. py:attribute:: MyClass.value :type: int The current value.
py:data
.. py:data:: MAX_RETRIES :value: 3 Maximum number of retry attempts.
py:exception
.. py:exception:: MyError Raised when something goes wrong.
py:module
.. py:module:: mypackage.core Core functionality for mypackage.
py:decorator
.. py:decorator:: cached(func) Cache the return value of *func*.
See Also
seealso directive
.. seealso:: :func:`os.path.join`, :class:`pathlib.Path`
Toctree (Sphinx)
toctree directive
.. toctree:: :maxdepth: 2 :caption: Contents installation usage api
toctree with numbered entries
.. toctree:: :numbered: intro guide/installation guide/usage guide/api
Glossary
glossary directive
.. glossary::
RST
reStructuredText — a lightweight markup language.
Sphinx
A documentation generator for Python projects.glossary (sorted)
.. glossary::
:sorted:
Zebra
A striped animal.
Aardvark
An ant-eating mammal.Mixed Sphinx Roles in Prose
Mixed roles in a paragraph
Use :func:`json.dumps` or :func:`json.loads` to serialize data. The :class:`dict` type maps :class:`str` keys to values. See :pep:`484` for type hints and :pep:`526` for variable annotations. Press :kbd:`Ctrl+D` or call :func:`exit` to quit the REPL.
----
This page was generated automatically. Run python tools/generate_demo_page.py from the repository root to refresh it.
Styling
rich-rst uses Rich <https://rich.readthedocs.io/>'s powerful styling and theming system to customize the appearance of rendered reStructuredText documents. This page explains how to personalize the visual style of your RST output.
- Overview
- How Styling Works
Customizing Styles
- Via Console Theme
- Modifying Console Theme At Runtime
- Using a Theme File
Customizable Style Names
- Headings
- Admonitions
- Inline text
- References
- Block elements
- Lists
- Tables
- Definition lists and field lists
- Option lists
- Sphinx-specific elements
- Other elements
- Full Customization Example
- Tips for Effective Styling
- See Also
Overview
rich-rst renders RST elements (headings, admonitions, lists, etc.) using Rich renderables, each styled with a specific style name from the Rich console's theme. The default styles provide sensible colors and formatting, but you can override them to match your preferences or theme.
All style names used by rich-rst follow the restructuredtext.* naming convention, making them easy to identify and customize.
How Styling Works
When rich-rst renders a document, it retrieves styles for each element using the current Rich console's theme. If a style name is not defined in the theme, rich-rst uses a built-in default style, ensuring that output always looks reasonable.
This approach has several advantages:
- Flexibility: Styles are defined centrally in the console's theme, not hardcoded.
- Consistency: Your custom styles automatically apply to all RST documents rendered with the same console.
- Fallback defaults: Every style name has a sensible default, so rendering never fails even with incomplete theme definitions.
Customizing Styles
There are several ways to customize rich-rst styles, depending on your use case.
Via Console Theme
The most straightforward way to customize styles is to create a Rich console with a custom theme and pass it to the rendering code. Here's an example:
from rich.console import Console
from rich.theme import Theme
from rich_rst import RestructuredText
# Create a custom theme
custom_theme = Theme({
"restructuredtext.title.level.1": "bold magenta",
"restructuredtext.title.level.2": "bold cyan",
"restructuredtext.note": "bold green on blue",
"restructuredtext.warning": "bold yellow on red",
"restructuredtext.reference": "cyan underline",
})
# Create a Rich console with your custom theme
console = Console(theme=custom_theme)
rst_document = """
Example Document
================
This is a **note**:
.. note::
This is styled with your custom theme!
Visit `this site <https://example.com>`_ for more info.
"""
# Render using the console
console.print(RestructuredText(rst_document))Modifying Console Theme At Runtime
If you already have a console instance, you can modify its theme directly:
from rich.console import Console
from rich_rst import RestructuredText
console = Console()
# Customize specific styles in the console's theme
console.push_style("restructuredtext.title.level.1", "bold magenta")
console.push_style("restructuredtext.note", "bold cyan on dark_blue")
rst_document = """
Heading
=======
.. note::
This note uses the customized style.
"""
console.print(RestructuredText(rst_document))Using a Theme File
Rich supports loading themes from JSON files. This is useful for sharing themes or organizing complex style definitions:
{
"restructuredtext.title.level.1": "bold #ff00ff",
"restructuredtext.title.level.2": "bold #00ffff",
"restructuredtext.title.level.3": "bold underline #ffff00",
"restructuredtext.note": "bold white on #0066ff",
"restructuredtext.warning": "bold white on #ff3300",
"restructuredtext.error": "bold white on #ff0000",
"restructuredtext.admonition": "bold #00ff00",
"restructuredtext.reference": "blue underline"
}Save this as my_theme.json, then load it in your code:
from rich.console import Console
from rich.theme import Theme
from rich_rst import RestructuredText
# Load the theme from a JSON file
theme = Theme.read("my_theme.json")
console = Console(theme=theme)
rst_document = "Your RST content here..."
console.print(RestructuredText(rst_document))Customizable Style Names
Below is a comprehensive list of all style names that rich-rst uses. You can customize any of these by defining them in your console's theme.
Headings
Headings are organized by level, and rich-rst supports up to 6 levels:
restructuredtext.title.level.1 (default: "bold" with double-line box) restructuredtext.title.level.2 (default: "bold" with rounded box) restructuredtext.title.level.3 (default: "bold underline") restructuredtext.title.level.4 (default: "bold") restructuredtext.title.level.5 (default: "underline") restructuredtext.title.level.6 (default: "italic")
Admonitions
Admonition boxes (.. note::, .. warning::, etc.):
restructuredtext.note (default: "bold white") restructuredtext.warning (default: "bold yellow") restructuredtext.error (default: "bold red") restructuredtext.danger (default: "bold white on red") restructuredtext.tip (default: "bold green") restructuredtext.hint (default: "yellow") restructuredtext.important (default: "bold blue") restructuredtext.caution (default: "red") restructuredtext.attention (default: "bold black on yellow") restructuredtext.admonition (default: "bold white")
Inline text
Styles applied to inline elements:
restructuredtext.text (default: "default on default not underline") restructuredtext.emphasis (default: "italic") restructuredtext.strong (default: "bold") restructuredtext.title_reference (default: "italic") restructuredtext.inline_codeblock (default: "grey78 on grey7") restructuredtext.subscript (default: "none") restructuredtext.superscript (default: "none") restructuredtext.abbreviation (default: "none") restructuredtext.acronym (default: "none") restructuredtext.math (default: "italic") restructuredtext.inline (default: "none")
References
Hyperlinks, citations, footnotes, and substitution references:
restructuredtext.reference (default: "blue underline on default") restructuredtext.citation_border (default: "grey74") restructuredtext.citation_reference (default: "grey74") restructuredtext.footnote_reference (default: "grey74") restructuredtext.substitution_reference (default: "none")
Block elements
Block quotes, code blocks, figures, and horizontal rules:
restructuredtext.blockquote_text (default: "white") restructuredtext.blockquote_attribution_marker (default: "bright_magenta") restructuredtext.blockquote_attribution_text (default: "grey89") restructuredtext.literal_block_border (default: "grey58") restructuredtext.figure_border (default: "blue") restructuredtext.hr (default: "yellow") restructuredtext.caption (default: "bold")
Lists
Bullet lists and enumerated lists:
restructuredtext.bullet_list_marker (default: "bold yellow") restructuredtext.bullet_list_text (default: "none") restructuredtext.enumerated_list_marker (default: "bold yellow") restructuredtext.enumerated_text (default: "none")
Tables
Table headers and cell text:
restructuredtext.table_header (default: "bold") restructuredtext.table_cell (default: "none")
Definition lists and field lists
restructuredtext.term_style (default: "none") restructuredtext.classifier_style (default: "cyan") restructuredtext.definitions_style (default: "none") restructuredtext.field_name (default: "bold") restructuredtext.field_value (default: "none")
Option lists
Command-line option descriptions:
restructuredtext.option_string (default: "none") restructuredtext.option_argument (default: "none") restructuredtext.option_child_text_separator (default: "none") restructuredtext.option_description (default: "none")
Sphinx-specific elements
Styles used when sphinx_compat=True is set:
restructuredtext.seealso (default: "bold white") restructuredtext.centered (default: "bold") restructuredtext.py_desc (default: "bold blue") restructuredtext.toctree (default: "bold cyan") restructuredtext.literalinclude (default: "grey58") restructuredtext.versionadded (default: "bold green") restructuredtext.versionchanged (default: "bold cyan") restructuredtext.deprecated (default: "bold yellow") restructuredtext.deprecated_removed (default: "bold red") restructuredtext.glossary (default: "bold")
Other elements
restructuredtext.rubric (default: "italic dim") restructuredtext.problematic (default: "none") restructuredtext.topic (default: "bold cyan") restructuredtext.footer (default: "none") restructuredtext.footer_border (default: "grey74")
Full Customization Example
Here's a complete example that customizes multiple aspects of rich-rst styling:
from rich.console import Console
from rich.theme import Theme
from rich_rst import RestructuredText
# Create a comprehensive custom theme
dark_theme = Theme({
# Headings - professional blue/purple gradient
"restructuredtext.title.level.1": "bold bright_blue",
"restructuredtext.title.level.2": "bold bright_cyan",
"restructuredtext.title.level.3": "bold cyan",
"restructuredtext.title.level.4": "cyan",
"restructuredtext.title.level.5": "dim cyan",
"restructuredtext.title.level.6": "italic dim cyan",
# Admonitions - semantic colors
"restructuredtext.note": "bold white on dark_blue",
"restructuredtext.warning": "bold bright_yellow on dark_goldenrod",
"restructuredtext.error": "bold bright_white on dark_red",
"restructuredtext.tip": "bold bright_green on dark_green",
"restructuredtext.important": "bold bright_magenta",
"restructuredtext.danger": "bold bright_white on dark_red",
# Links and references
"restructuredtext.reference": "bright_cyan underline",
"restructuredtext.toctree": "bright_cyan",
# Lists
"restructuredtext.bullet_list_marker": "bright_yellow",
# Code and literals
"restructuredtext.literalinclude": "grey66",
})
# Create console and render
console = Console(theme=dark_theme)
rst_content = """
API Documentation
=================
Overview
--------
This is an important API.
.. warning::
Do not use this in production without testing!
.. note::
See the `official docs <https://example.com>`_ for more information.
Features
--------
- Feature one
- Feature two
- Feature three
.. tip::
You can combine multiple features for powerful workflows.
"""
console.print(RestructuredText(rst_content))Tips for Effective Styling
- Use semantic colors: Map admonitions to meaningful colors (red for danger, yellow for warnings, green for tips).
- Ensure contrast: Make sure your chosen colors have sufficient contrast against your terminal background for easy reading.
- Be consistent: Use a limited palette of related colors for visual coherence.
- Test in your environment: Terminal color rendering varies across platforms and configurations, so test your theme in your actual terminal.
Standard Rich color names: Rich supports a wide variety of color names:
- Basic: black, red, green, yellow, blue, magenta, cyan, white
- Bright: bright_red, bright_green, bright_blue, etc.
- Grayscale: grey0 through grey100
- Named colors: dark_red, navy_blue, gold, etc.
- Hex colors: #ff0000, #00ff00, etc.
Text attributes: You can combine colors with attributes:
- bold - bold/bright text
- dim - dimmed/faint text
- italic - italic text
- underline - underlined text
- blink - blinking text
- reverse - reversed/inverted colors
- conceal - hidden text
- strike - strike-through text
See Also
- Rich documentation on styling <https://rich.readthedocs.io/en/latest/style.html>
- Rich documentation on themes <https://rich.readthedocs.io/en/latest/themes.html>
- reStructuredText reference <https://docutils.sourceforge.io/rst.html>
Extension API
This page explains how to make rich-rst render your own docutils node types.
If you have a custom directive/transform that creates custom nodes, this is the API you use to tell rich-rst how those nodes should appear.
The entry point is rich_rst.RSTVisitor.
When should I use this?
Use this API when all of the following are true:
- You already have (or will create) a custom docutils node class.
- You want rich-rst output to show that node in a custom way.
- Built-in rendering is not enough.
If you only use standard reStructuredText/Sphinx features, you usually do not need this page.
Overview
During rendering, rich-rst visits nodes in the parsed document tree.
For each node:
- For each node, rich_rst.RSTVisitor checks its custom registry.
- If a handler is registered for that exact node class, the handler runs.
- Otherwise, normal visit_* / depart_* method lookup is used.
Important: registration is by exact class match (not by subclass hierarchy).
The custom registry is class-level and stores:
{node_class: (visit_fn, depart_fn)}Quick start (5 steps)
- Define (or import) your custom node class.
- Write a visit handler with signature handler(visitor, node).
- Register it with rich_rst.RSTVisitor.register_visitor().
- Render your document normally.
- Unregister when the handler should no longer be active.
Minimal pattern:
from rich_rst import RSTVisitor
def visit_my_node(visitor, node):
# Add any Rich renderable you want.
visitor.renderables.append(...)
RSTVisitor.register_visitor(MyNode, visit_fn=visit_my_node)
try:
... # render documents
finally:
RSTVisitor.unregister_visitor(MyNode)Public methods
- RSTVisitor.register_visitor(node_class, visit_fn=None, depart_fn=None)
Register custom handlers for a node class.
node_class is the docutils node class to handle. visit_fn runs when entering the node. depart_fn is optional and runs after children are visited.
Direct form:
RSTVisitor.register_visitor(MyNode, visit_fn=my_visit, depart_fn=my_depart)
Decorator form (registers the function as visit_fn):
@RSTVisitor.register_visitor(MyNode) def my_visit(visitor, node): ...- RSTVisitor.unregister_visitor(node_class)
Remove a registration. Calling this for a class that is not registered is safe and does nothing.
- RSTVisitor.list_registered_visitors()
Return a snapshot of the registry as a dict. Mutating the returned dict does not change the live registry.
Handler contract
Visit/depart handlers are called as handler(visitor, node).
Inside handlers:
- visitor is the active rich_rst.RSTVisitor instance.
- node is the current docutils node instance.
Common patterns:
- Add Rich renderables through visitor.renderables.append(...).
- Raise docutils.nodes.SkipChildren from a visit handler when you fully handle a node and do not want child traversal.
- Use a depart handler when you need closing behavior after children are visited.
End-to-end example (node + directive + RST)
This example shows the full flow most users need:
- Define a custom node class.
- Define a directive that emits that node.
- Register a visitor handler for that node.
Render an RST document that uses the directive.
from rich import print from rich.panel import Panel from rich_rst import RestructuredText, RSTVisitor from rich_rst._vendor import docutils class MyNode(docutils.nodes.General, docutils.nodes.Body, docutils.nodes.Element): pass class MyCalloutDirective(docutils.parsers.rst.Directive): has_content = True def run(self): node = MyNode() self.state.nested_parse(self.content, self.content_offset, node) return [node] def visit_my_node(visitor, node): # Render the node as a Rich panel and skip normal child traversal. visitor.renderables.append(Panel(node.astext(), title="my-callout", border_style="cyan")) raise docutils.nodes.SkipChildren() def enable_extensions(): docutils.parsers.rst.directives.register_directive("my-callout", MyCalloutDirective) RSTVisitor.register_visitor(MyNode, visit_fn=visit_my_node) def disable_extensions(): RSTVisitor.unregister_visitor(MyNode) enable_extensions() try: rst_source = ( "Before.\n\n" ".. my-callout::\n\n" " This text is parsed into MyNode and rendered by visit_my_node.\n\n" "After.\n" ) print(RestructuredText(rst_source)) finally: disable_extensions()
Notes:
- register_directive and register_visitor are both global registrations.
- In tests, prefer fixture-based setup/teardown to avoid cross-test leakage.
- The try/finally above ensures the visitor is always unregistered.
Example: decorator registration
Use this form when you like declaration-style setup:
from rich.text import Text
from rich_rst import RSTVisitor
from rich_rst._vendor import docutils
class DecoratedNode(docutils.nodes.General, docutils.nodes.Inline, docutils.nodes.Element):
pass
@RSTVisitor.register_visitor(DecoratedNode)
def visit_decorated(visitor, node):
visitor.renderables.append(Text("from decorator"))
raise docutils.nodes.SkipChildren()
# later, when no longer needed:
RSTVisitor.unregister_visitor(DecoratedNode)Subclass behavior
Registrations on rich_rst.RSTVisitor are global to that class and are visible to all instances.
If you call register_visitor on a subclass of RSTVisitor, that subclass gets its own registry dictionary. This isolates subclass-specific extensions from the base class and from sibling subclasses.
Troubleshooting
- Handler did not run: Confirm you registered the exact node class being produced.
- Custom output appears twice: If your visit handler fully handles content, raise docutils.nodes.SkipChildren.
- Tests affect each other: Unregister handlers in test teardown/fixtures.
- Registry changes do not stick: list_registered_visitors() returns a snapshot copy, not a live dict.
Recommendations
- Register handlers at application startup, not per document.
- Unregister temporary handlers in tests or short-lived plugin scopes.
- Keep handlers narrow and side-effect free except for appending renderables.
Include Directive
rich-rst provides a custom implementation of the standard .. include:: directive that resolves file paths relative to the source document and includes path-traversal protection.
- Basic Usage
- Path Resolution
- Security: Path-Traversal Protection
- Options
- Error Handling
- Enabling the Directive
- See Also
Basic Usage
Use .. include:: to insert the contents of another RST file inline in your document:
Main document text. .. include:: chapter1.rst More main document text.
The included file is parsed as RST and rendered as if its content had been written directly in the parent document.
Path Resolution
Paths are resolved relative to the source document's directory:
.. include:: sections/intro.rst .. include:: ../shared/footer.rst
When rendering from a string (i.e. no source file path is known, or the source is <string>/ <stdin>), paths are resolved relative to the current working directory.
Security: Path-Traversal Protection
The .. include:: directive rejects paths that would escape outside the source document's directory. For example, the following directive will produce a warning admonition instead of including the file:
.. include:: /etc/passwd
The warning message will be rendered in place of the included content, making security issues visible during rendering.
Options
The following options are supported:
- encoding
Character encoding of the included file. Defaults to utf-8.
.. include:: data.rst :encoding: latin-1
- start-line
First line (0-based) of the file to include. Lines before this index are omitted.
.. include:: long_file.rst :start-line: 10
- end-line
Last line (exclusive, 0-based) of the file to include. Lines from this index onwards are omitted.
.. include:: long_file.rst :start-line: 10 :end-line: 20
Combining start-line and end-line selects a slice of the file:
.. include:: reference.rst :start-line: 5 :end-line: 15
Error Handling
If the file cannot be read (missing file, permission error, encoding error), rich-rst emits a warning admonition in place of the included content:
╭──────────────────── Warning ─────────────────────╮ │ Could not include file: 'missing_file.rst' │ ╰───────────────────────────────────────────────────╯
This means rendering always succeeds; errors are surfaced as visible warnings rather than hard failures.
Enabling the Directive
.. include:: is always available in rich-rst — no extra configuration is needed. It is registered automatically when the first RST document is rendered.
Note:
This directive is separate from .. literalinclude::, which includes a file as a code block rather than inlining it as RST.
See Also
- RestructuredText — the main rendering class
- Sphinx & RST Demo Gallery <> — full kitchen sink style list of supported RST elements
Limitations and Behavior Notes
This page documents terminal-specific limitations and behavior differences so output is predictable when rendering reStructuredText with rich-rst.
Terminal rendering constraints
rich-rst targets terminal output, so some docutils features cannot map 1:1 to full HTML/Sphinx rendering.
- math (inline math) is not fully supported as a formatted equation object.
- math_block is rendered as plain math text in a labeled panel.
- Visual decorations that depend on page layout are simplified for terminals.
- Some Sphinx directives are intentionally no-op to avoid parse errors.
Sphinx compatibility behavior
When sphinx_compat=True (default), rich-rst registers many Sphinx roles/directives to improve docstring and Sphinx-source compatibility.
Important caveats:
- .. literalinclude:: does not read files from disk; it renders a stub panel showing the referenced file name.
- .. only:: always renders content; the expression is accepted but not evaluated.
- .. hlist:: accepts :columns:, but terminal output is rendered as a regular bullet list.
- .. highlight:: is accepted silently and has no direct visual output.
- Some context directives are accepted silently (for example index and currentmodule variants) to prevent noisy system messages.
API vs CLI defaults
The defaults are intentionally close, but one common difference is easy to miss:
- Python API RestructuredText(..., show_errors=True) defaults to showing parse/system messages.
- CLI python -m rich_rst ... defaults to hiding parse/system messages unless --show-errors is passed.
If you compare API and CLI output, align this option first.
What is intentionally simplified
- Layout-specific HTML behavior is approximated with Rich panels, tables, and styled text.
- Links are rendered for terminal click/open support where possible.
- Source-level Sphinx metadata directives may be consumed with no visual output when their purpose is non-terminal metadata.
Reference pages
- See Sphinx & RST Demo Gallery <> for practical RST and Sphinx examples.
- See API Reference <> for complete API and CLI option details.
Author
Wasi Master aka. Arian Mollik Wasi
Copyright
2026, Wasi Master aka. Arian Mollik Wasi