This commit is contained in:
Will McGugan 2021-02-14 14:08:05 +00:00
parent a5dc32dcf2
commit 97f4ffd556
6 changed files with 179 additions and 56 deletions

View file

@ -21,8 +21,7 @@ Welcome to Rich's documentation!
prompt.rst
columns.rst
group.rst
live.rst
group.rst
markdown.rst
padding.rst
panel.rst
@ -30,6 +29,8 @@ Welcome to Rich's documentation!
syntax.rst
tables.rst
tree.rst
live.rst
layout.rst
protocol.rst

80
docs/source/layout.rst Normal file
View file

@ -0,0 +1,80 @@
Layout
======
Rich offers a :class:`~rich.layout.Layout` renderable which can be used to divide the screen area in to parts where each part may contain another renderable. It is most often used with :ref:`Live` to create full-screen "applications", but may be used standalone.
To see an example of a Layout, run the following from the command line::
python -m rich.layout
To define a layout, construct a Layout object and print it::
from rich import print
from rich.layout import Layout
layout = Layout()
print(layout)
This will draw a box the size of the terminal with some information regarding the layout. The box is a "placeholder" because we have yet to add any content to it. Before we do that, we can call the :meth:`~rich.layout.Layout.split` method to divide the layout in to two parts::
layout.split(name="upper")
layout.split(name="lower", direction="horizontal")
print(layout)
This will divide the terminal screen in to two equal sized portions one on top of the other. The ``direction="horizontal"`` argument tells the Layout class that further splits should be stacked left-to-right rather than top-to-bottom. The `name` attribute is an internal identifier we can use to look up the sub-layout later. Let's use that to create another split::
layout["lower"].split(name="left")
layout["lower"].split(name="right")
print(layout)
You should now see the screen area divided in to 3 portions; An upper half and a lower half that is split in to two left and right quarter portions. You can continue to call split() create as many parts to the screen as you wish.
Setting renderables
-------------------
The Layout class would not be that useful if it only displayed placeholders. Fortunately we can tell the layout (or sub-layout) to display text or any other Rich renderable in it's portion of the screen area. To set a renderable, call :meth:`~rich.layout.Layout.update` with your renderable. Here is an example::
layout["left"].update("The mystery of life isn't a problem to solve, but a reality to experience.")
print(layout)
Fixed size
----------
You can set a sub-layout to use a fixed size by setting the ``size`` argument on :meth:`~rich.layout.Layout.split` or by setting the attribute layout. Here's an example::
layout["upper"].size = 10
print(layout)
This will set the upper portion to be exactly 10 rows, no matter the size of the terminal.
Ratio
-----
In addition to a fixed size, you can also assign a ratio* to a Layout which defines how much of the screen the layout should occupy in relation to other layouts. For example, lets reset the size and set the ratio of the upper layout to 2::
layout["upper"].size = None
layout["upper"].ratio = 2
print(layout)
This makes the top layout take up two thirds of the space and the two lower layouts the remaining third. This is because the default ratio is 1, giving the upper and lower layouts a combined total of 3.
Visibility
----------
By default layouts are visible, but you can make a layout invisible by setting the ``visible`` attribute to False. Here's an example::
layout["upper"].visible = False
print(layout)
This has made the top layout invisible, and the "lower" layout expands to fill the available space. Set ``visible`` to True to bring it back::
layout["upper"].visible = True
print(layout)
Tree
----
To help visualize complex layouts you can print the ``tree`` attribute which will display a summary of the layout with a tree::
print(layout.tree)

View file

@ -13,19 +13,11 @@ For a demonstration of a live display, running the following command:
If you see ellipsis "...", this indicates that the terminal is not tall enough to show the full table.
Basic Usage
-----------
Basic usage
~~~~~~~~~~~
The basic usage can be split into two use cases.
To create a live display, construct a :class:`~rich.live.Live` object with a renderable and use it has a context manager. The live display will persist for the duration of the context. You can update the renderable to update the display::
1. Same Renderable
~~~~~~~~~~~~~~~~~~
When keeping the same renderable, pass the :class:`~rich.console.RenderableType` you would like to see updating and provide
a ``refresh_per_second`` parameter. The Live :class:`~rich.live.Live` will automatically update the console at the provided refresh rate.
**Example**::
import time
@ -44,13 +36,11 @@ a ``refresh_per_second`` parameter. The Live :class:`~rich.live.Live` will autom
table.add_row(f"{row}", f"description {row}", "[red]ERROR")
2. New Renderable
~~~~~~~~~~~~~~~~~
Updating the renderable
~~~~~~~~~~~~~~~~~~~~~~~
You can also provide a new renderable to :class:`~rich.live.Live` using the :meth:`~rich.live.Live.update` function. This allows you to
completely change the live display.
You can also change the renderable on-the-fly by calling the :meth:`~rich.live.Live.update` method. This may be useful if the information you wish to display is too dynamic to generate by updating a single renderable. Here is an example:
**Example**::
import random
import time
@ -60,7 +50,7 @@ completely change the live display.
def generate_table() -> Table:
"""Make a new table."""
table = Table()
table.add_column("ID")
table.add_column("Value")
@ -74,22 +64,24 @@ completely change the live display.
return table
with Live(refresh_per_second=4) as live:
with Live(generate_table(), refresh_per_second=4) as live:
for _ in range(40):
time.sleep(0.4)
live.update(generate_table())
Advanced Usage
--------------
Transient Display
Alternate screen
~~~~~~~~~~~~~~~~
You can opt to show a Live display in the "alternate screen" by setting ``screen=False`` on the constructor. This will allow your live display to go full screen and restore the command prompt on exit.
You can use this feature in combination with :ref:`Layoout` to display sophisticated terminal "applications".
Transient display
~~~~~~~~~~~~~~~~~
Normally when you exit live context manager (or call :meth:`~rich.live.Live.stop`) the last refreshed item remains in the terminal with the cursor on the following line.
You can also make the live display disappear on exit by setting ``transient=True`` on the Live constructor. Here's an example::
with Live(transient=True) as live:
...
You can also make the live display disappear on exit by setting ``transient=True`` on the Live constructor.
Auto refresh
~~~~~~~~~~~~
@ -100,28 +92,20 @@ You should set this to something lower than 4 if you know your updates will not
You might want to disable auto-refresh entirely if your updates are not very frequent, which you can do by setting ``auto_refresh=False`` on the constructor.
If you disable auto-refresh you will need to call :meth:`~rich.live.Live.refresh` manually or :meth:`~rich.live.Live.update` with ``refresh=True``.
Vertical Overflow
Vertical overflow
~~~~~~~~~~~~~~~~~
By default, the live display will display ellipsis if the renderable is too large for the terminal. You can adjust this by setting the
``vertical_overflow`` argument on the :class:`~rich.live.Live` constructor.
- crop: Show renderable up to the terminal height. The rest is hidden.
- ellipsis: Similar to crop except last line of the terminal is replaced with "...". This is the default behavior.
- visible: Will allow the whole renderable to be shown. Note that the display cannot be properly cleared in this mode.
- "crop" Show renderable up to the terminal height. The rest is hidden.
- "ellipsis" Similar to crop except last line of the terminal is replaced with "...". This is the default behavior.
- "visible" Will allow the whole renderable to be shown. Note that the display cannot be properly cleared in this mode.
.. note::
Once the live display stops on a non-transient renderable, the last frame will render as **visible** since it doesn't have to be cleared.
Complex Renders
~~~~~~~~~~~~~~~
Refer to the :ref:`Render Groups` about combining multiple :class:`RenderableType` together so that it may be passed into the :class:`~rich.live.Live` constructor
or :meth:`~rich.live.Live.update` method.
For more powerful structuring it is also possible to use nested tables.
Print / log
~~~~~~~~~~~
@ -172,6 +156,7 @@ Note that only a single live context may be active at any one time. The followin
with console.status("working"): # Will not work
do_work()
In practice this is rarely a problem because you can display any combination of renderables in a Live context.
Examples
--------