mirror of https://github.com/Textualize/rich.git
72 lines
3.6 KiB
ReStructuredText
72 lines
3.6 KiB
ReStructuredText
|
|
.. _protocol:
|
|
|
|
Console Protocol
|
|
================
|
|
|
|
Rich supports a simple protocol to add rich formatting capabilities to custom objects, so you can :meth:`~rich.console.Console.print` your object with color, styles and formatting.
|
|
|
|
Use this for presentation or to display additional debugging information that might be hard to parse from a typical ``__repr__`` string.
|
|
|
|
|
|
Console Customization
|
|
---------------------
|
|
|
|
The easiest way to customize console output for your object is to implement a ``__rich__`` method. This method accepts no arguments, and should return an object that Rich knows how to render, such as a :class:`~rich.text.Text` or :class:`~rich.table.Table`. If you return a plain string it will be rendered as :ref:`console_markup`. Here's an example::
|
|
|
|
class MyObject:
|
|
def __rich__(self) -> str:
|
|
return "[bold cyan]MyObject()"
|
|
|
|
If you were to print or log an instance of ``MyObject`` it would render as ``MyObject()`` in bold cyan. Naturally, you would want to put this to better use, perhaps by adding specialized syntax highlighting.
|
|
|
|
|
|
Console Render
|
|
--------------
|
|
|
|
The ``__rich__`` method is limited to a single renderable object. For more advanced rendering, add a ``__console__`` method to your class.
|
|
|
|
The ``__console__`` method should accept a :class:`~rich.console.Console` and a :class:`~rich.console.ConsoleOptions` instance. It should return an iterable of other renderable objects. Although that means it *could* return a container such as a list, it generally easier implemented by using the ``yield`` statement (making the method a generator).
|
|
|
|
Here's an example of a ``__console__`` method::
|
|
|
|
from rich.console import Console, ConsoleOptions, RenderResult
|
|
|
|
@dataclass
|
|
class Student:
|
|
id: int
|
|
name: str
|
|
age: int
|
|
def __console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
|
|
yield f"[b]Student:[/b] #{self.id}"
|
|
my_table = Table("Attribute, "Value")
|
|
my_table.add_row("name", self.name)
|
|
my_table.add_row("age", str(self.age))
|
|
yield my_table
|
|
|
|
If you were to print a ``Student`` instance, it would render a simple table to the terminal.
|
|
|
|
|
|
Low Level Render
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
For complete control over how a custom object is rendered to the terminal, you can yield :class:`~rich.segment.Segment` objects. A Segment consists of a piece of text and an optional Style. The following example, writes multi-colored text when rendering a ``MyObject`` instance::
|
|
|
|
class MyObject:
|
|
def __console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
|
|
yield Segment("My", "magenta")
|
|
yield Segment("Object", green")
|
|
yield Segment("()", "cyan")
|
|
|
|
|
|
Console Width
|
|
~~~~~~~~~~~~~
|
|
|
|
Sometimes Rich needs to know how many characters an object will take up when rendering. The :class:`~rich.table.Table` class, for instance, will use this information to calculate the optimal dimensions for the columns. If you aren't using one of the standard classes, you will need to supply a ``__console_width__`` method which accepts the maximum width as an integer and returns a :class:`~rich.render_width.RenderWidth` object. The RenderWidth object should contain the *minimum* and *maximum* number of characters required to render.
|
|
|
|
For example, if we are rendering a chess board, it would require a minimum of 8 characters to render. The maximum can be left as the maximum available width (assuming a centered board)::
|
|
|
|
class ChessBoard:
|
|
def __console_width__(self, max_width: int) -> RenderWidth:
|
|
return RenderWidth(8, max_width)
|