Layout, columns and groups¶
from rs_rich.columns import Columns
from rs_rich.console import Console
from rs_rich.containers import Renderables
from rs_rich.layout import Layout
from rs_rich.panel import Panel
The renderables that arrange others. Each corresponds to the Rich class of the same name and renders byte for byte as Rich 15.0.0 does.
Columns¶
Columns(renderables=None, padding=(0, 1), *, width=None, expand=False,
equal=False, column_first=False, right_to_left=False, align=None,
title=None)
columns.add_renderable(renderable)
Renderables in as many columns as fit the width. equal gives every column
the widest item's width, expand fills the width, column_first fills top to
bottom, right_to_left starts on the right, align aligns each item in its
column, width fixes the column width and title is drawn above.
console = Console(width=30)
words = "alpha beta gamma delta epsilon zeta eta theta".split()
console.print(Columns(words))
console.print(Columns(words, equal=True, column_first=True))
Group¶
rich.console.Group: several renderables one after another, as one
renderable (in a panel, say). With fit the group measures as its widest
child; without it, as the whole width. The group decorator turns a function
that yields renderables into one that returns a Group.
from rs_rich.console import Group, group
console = Console(width=30)
console.print(Panel.fit(Group("first", Panel("second"))))
@group()
def lines():
yield "one"
yield "two"
console.print(Panel.fit(lines()))
╭────────────╮
│ first │
│ ╭────────╮ │
│ │ second │ │
│ ╰────────╯ │
╰────────────╯
╭─────╮
│ one │
│ two │
╰─────╯
rich.containers.Renderables (a list that
renders its items in turn) is rs_rich.containers.Renderables, and
rich.containers.Lines is rs_rich.containers.Lines (see Text).
rich.measure.measure_renderables(console, options, renderables) is
rs_rich.measure.measure_renderables.
Layout¶
A region of fixed height divided into rows and columns. split_column(...)
stacks sub-layouts, split_row(...) puts them side by side, split(...,
splitter="row") does either (an unknown splitter raises NoSplitter), and
add_split(...) and unsplit() change a split. A sub-layout is sized by
size, or shares the space by ratio (never below minimum_size); an
invisible one is left out. layout["name"] (or layout.get("name")) finds a
sub-layout and update(renderable) sets its content; a layout with no content
shows a placeholder with its name and size, as in Rich.
console = Console(width=40, height=10)
layout = Layout()
layout.split_column(Layout(name="header", size=3), Layout(name="body"))
layout["body"].split_row(Layout(name="left"), Layout(name="right", ratio=2))
layout["header"].update(Panel("header"))
layout["left"].update("left side")
console.print(layout)
╭──────────────────────────────────────╮
│ header │
╰──────────────────────────────────────╯
left side ╭─── 'right' (27 x 7) ────╮
│ Layout( │
│ name='right', │
│ ratio=2 │
│ ) │
│ │
╰─────────────────────────╯
A layout's height is the console's (or the height= given to print).
layout.tree is a Tree of the structure, layout.render(console,
options) returns {layout: LayoutRender(region, lines)} for each leaf, and
layout.map holds the last render's. Region, LayoutRender, Splitter,
RowSplitter, ColumnSplitter and LayoutError are in rs_rich.layout too.
⬍ Layout()
├── ⬍ Layout(name='header', size=3)
└── ⬌ Layout(name='body')
├── ⬍ Layout(name='left')
└── ⬍ Layout(name='right', ratio=2)
layout.refresh_screen(console, name) renders the leaf called name again,
into the region it had when the layout was last printed, and writes it over
that part of the alternate screen (console.set_alt_screen(True), or a
Screen), as Rich does. Outside the alternate screen it raises
NoAltScreen, and a name that was not a leaf of the last render raises
KeyError. Console.update_screen(renderable, region=...) and
Console.update_screen_lines(lines, x, y) are there too.
A custom Splitter subclass raises NotImplementedError; the row and column
splitters are supported.