This commit is contained in:
Will McGugan 2020-06-27 22:16:00 +01:00
parent 79475b2e48
commit ab178c2acc
5 changed files with 100 additions and 127 deletions

View File

@ -8,120 +8,62 @@ Rich defines a number of ways of drawing boxes and lines such as those used in t
from rich import box
table = Table(box=box.SQUARE)
The constants are as follows:
.. note::
Some of the box drawing characters will not display correctly on Windows legacy terminal (cmd.exe) with *raster* fonts, and are disabled by default. If you want the full range of box options on Windows legacy terminal, use a *truetype* font and set the ``safe_box`` parameter on the Table class to ``False``.
The following table is generated with the following command::
python -m rich.box
.. raw:: html
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #800080"> box.ASCII </span>
+-------------------------+
|<span style="color: #7f7f7f; font-weight: bold"> </span>|<span style="color: #7f7f7f; font-weight: bold"> </span>|
|------------+------------|
|<span style="color: #7f7f7f"> </span>|<span style="color: #7f7f7f"> </span>|
|------------+------------|
|<span style="color: #7f7f7f; font-weight: bold"> </span>|<span style="color: #7f7f7f; font-weight: bold"> </span>|
+-------------------------+
<span style="color: #800080"> box.SQUARE </span>
┌────────────┬────────────┐
│<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>│
├────────────┼────────────┤
│<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>│
├────────────┼────────────┤
│<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>│
└────────────┴────────────┘
<span style="color: #800080"> box.MINIMAL </span>
<pre style="font-size:90%;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #008000">╭────────────────────────────────────────────────────────────────────────────────────────────────╮</span>
<span style="color: #008000">│</span> <span style="color: #008000; font-weight: bold">Box Constants</span> <span style="color: #008000">│
╰────────────────────────────────────────────────────────────────────────────────────────────────╯</span>
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
────────────┼────────────
<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>
────────────┼────────────
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
<span style="color: #800080"> box.ASCII </span> <span style="color: #800080"> box.SQUARE </span> <span style="color: #800080"> box.MINIMAL </span> <span style="color: #800080">box.MINIMAL_HEAVY_HEAD </span>
+---------------------+ ┌──────────┬──────────┐
|<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>|<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>| │<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>│ <span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>
|----------+----------| ├──────────┼──────────┤ ──────────┼────────── ━━━━━━━━━━┿━━━━━━━━━━
|<span style="color: #7f7f7f"> Cell </span>|<span style="color: #7f7f7f"> Cell </span>| │<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│ <span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>
|<span style="color: #7f7f7f"> Cell </span>|<span style="color: #7f7f7f"> Cell </span>| │<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│ <span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>
|----------+----------| ├──────────┼──────────┤ ──────────┼────────── ──────────┼──────────
|<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>|<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>| │<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>│ <span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>
+---------------------+ └──────────┴──────────┘
<span style="color: #800080"> box.MINIMAL_HEAVY_HEAD </span>
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
━━━━━━━━━━━━┿━━━━━━━━━━━━
<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>
────────────┼────────────
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
<span style="color: #800080">box.MINIMAL_DOUBLE_HEAD</span> <span style="color: #800080"> box.SIMPLE </span> <span style="color: #800080"> box.SIMPLE_HEAVY </span> <span style="color: #800080"> box.HORIZONTALS </span>
───────────────────────
<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>
══════════╪══════════ ─────────────────────── ╺━━━━━━━━━━━━━━━━━━━━━╸ ───────────────────────
<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span>
<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span> <span style="color: #7f7f7f"> Cell </span>
──────────┼────────── ─────────────────────── ╺━━━━━━━━━━━━━━━━━━━━━╸ ───────────────────────
<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span> <span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>
───────────────────────
<span style="color: #800080"> box.MINIMAL_DOUBLE_HEAD </span>
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
════════════╪════════════
<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>
────────────┼────────────
<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>
<span style="color: #800080"> box.ROUNDED </span> <span style="color: #800080"> box.HEAVY </span> <span style="color: #800080"> box.HEAVY_EDGE </span> <span style="color: #800080"> box.HEAVY_HEAD </span>
╭──────────┬──────────╮ ┏━━━━━━━━━━┳━━━━━━━━━━┓ ┏━━━━━━━━━━┯━━━━━━━━━━┓ ┏━━━━━━━━━━┳━━━━━━━━━━┓
│<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>│ ┃<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>┃<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>┃ ┃<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>┃ ┃<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>┃<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>┃
├──────────┼──────────┤ ┣━━━━━━━━━━╋━━━━━━━━━━┫ ┠──────────┼──────────┨ ┡━━━━━━━━━━╇━━━━━━━━━━┩
│<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│ ┃<span style="color: #7f7f7f"> Cell </span>┃<span style="color: #7f7f7f"> Cell </span>┃ ┃<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>┃ │<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│
│<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│ ┃<span style="color: #7f7f7f"> Cell </span>┃<span style="color: #7f7f7f"> Cell </span>┃ ┃<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>┃ │<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>│
├──────────┼──────────┤ ┣━━━━━━━━━━╋━━━━━━━━━━┫ ┠──────────┼──────────┨ ├──────────┼──────────┤
│<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>│ ┃<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>┃<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>┃ ┃<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>┃ │<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>│
╰──────────┴──────────╯ ┗━━━━━━━━━━┻━━━━━━━━━━┛ ┗━━━━━━━━━━┷━━━━━━━━━━┛ └──────────┴──────────┘
<span style="color: #800080"> box.SIMPLE </span>
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
───────────────────────────
<span style="color: #7f7f7f"> </span> <span style="color: #7f7f7f"> </span>
───────────────────────────
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
<span style="color: #800080"> box.SIMPLE_HEAVY </span>
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
╺━━━━━━━━━━━━━━━━━━━━━━━━━╸
<span style="color: #7f7f7f"> </span> <span style="color: #7f7f7f"> </span>
╺━━━━━━━━━━━━━━━━━━━━━━━━━╸
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
<span style="color: #800080"> box.HORIZONTALS </span>
───────────────────────────
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
───────────────────────────
<span style="color: #7f7f7f"> </span> <span style="color: #7f7f7f"> </span>
───────────────────────────
<span style="color: #7f7f7f; font-weight: bold"> </span> <span style="color: #7f7f7f; font-weight: bold"> </span>
───────────────────────────
<span style="color: #800080"> box.ROUNDED </span>
╭────────────┬────────────╮
│<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>│
├────────────┼────────────┤
│<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>│
├────────────┼────────────┤
│<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>│
╰────────────┴────────────╯
<span style="color: #800080"> box.HEAVY </span>
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃
┣━━━━━━━━━━━━╋━━━━━━━━━━━━┫
┃<span style="color: #7f7f7f"> </span>┃<span style="color: #7f7f7f"> </span>┃
┣━━━━━━━━━━━━╋━━━━━━━━━━━━┫
┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━┛
<span style="color: #800080"> box.HEAVY_EDGE </span>
┏━━━━━━━━━━━━┯━━━━━━━━━━━━┓
┃<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>┃
┠────────────┼────────────┨
┃<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>┃
┠────────────┼────────────┨
┃<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>┃
┗━━━━━━━━━━━━┷━━━━━━━━━━━━┛
<span style="color: #800080"> box.HEAVY_HEAD </span>
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃<span style="color: #7f7f7f; font-weight: bold"> </span>┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>│
├────────────┼────────────┤
│<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>│
└────────────┴────────────┘
<span style="color: #800080"> box.DOUBLE </span>
╔════════════╦════════════╗
║<span style="color: #7f7f7f; font-weight: bold"> </span>║<span style="color: #7f7f7f; font-weight: bold"> </span>║
╠════════════╬════════════╣
║<span style="color: #7f7f7f"> </span>║<span style="color: #7f7f7f"> </span>║
╠════════════╬════════════╣
║<span style="color: #7f7f7f; font-weight: bold"> </span>║<span style="color: #7f7f7f; font-weight: bold"> </span>║
╚════════════╩════════════╝
<span style="color: #800080"> box.DOUBLE_EDGE </span>
╔════════════╤════════════╗
║<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>║
╟────────────┼────────────╢
║<span style="color: #7f7f7f"> </span>│<span style="color: #7f7f7f"> </span>║
╟────────────┼────────────╢
║<span style="color: #7f7f7f; font-weight: bold"> </span>│<span style="color: #7f7f7f; font-weight: bold"> </span>║
╚════════════╧════════════╝
<span style="color: #800080"> box.DOUBLE </span> <span style="color: #800080"> box.DOUBLE_EDGE </span>
╔══════════╦══════════╗ ╔══════════╤══════════╗
║<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>║<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>║ ║<span style="color: #7f7f7f; font-weight: bold"> Header 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Header 2 </span>║
╠══════════╬══════════╣ ╟──────────┼──────────╢
║<span style="color: #7f7f7f"> Cell </span>║<span style="color: #7f7f7f"> Cell </span>║ ║<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>║
║<span style="color: #7f7f7f"> Cell </span>║<span style="color: #7f7f7f"> Cell </span>║ ║<span style="color: #7f7f7f"> Cell </span>│<span style="color: #7f7f7f"> Cell </span>║
╠══════════╬══════════╣ ╟──────────┼──────────╢
║<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>║<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>║ ║<span style="color: #7f7f7f; font-weight: bold"> Footer 1 </span>│<span style="color: #7f7f7f; font-weight: bold"> Footer 2 </span>║
╚══════════╩══════════╝ ╚══════════╧══════════╝
</pre>

View File

@ -348,9 +348,20 @@ DOUBLE_EDGE: Box = Box(
"""
)
LEGACY_WINDOWS_SUBSTITUTIONS = {
ROUNDED: SQUARE,
MINIMAL_HEAVY_HEAD: MINIMAL,
SIMPLE_HEAVY: SIMPLE,
HEAVY: SQUARE,
HEAVY_EDGE: SQUARE,
HEAVY_HEAD: SQUARE,
}
if __name__ == "__main__": # pragma: no cover
from rich.columns import Columns
from rich.panel import Panel
from .console import Console
from .table import Table
from .text import Text
@ -358,12 +369,6 @@ if __name__ == "__main__": # pragma: no cover
console = Console(record=True)
table = Table(width=80, show_footer=True, style="dim", border_style="not dim")
spaces = " " * 10
table.add_column(spaces, spaces)
table.add_column(spaces, spaces)
table.add_row(spaces, spaces)
BOXES = [
"ASCII",
"SQUARE",
@ -381,9 +386,21 @@ if __name__ == "__main__": # pragma: no cover
"DOUBLE_EDGE",
]
console.print(Panel("[bold green]Box Constants", style="green"), justify="center")
console.print()
columns = Columns(expand=False, padding=2)
for box_name in BOXES:
table = Table(width=80, show_footer=True, style="dim", border_style="not dim")
spaces = " " * 10
table.add_column("Header 1", "Footer 1")
table.add_column("Header 2", "Footer 2")
table.add_row("Cell", "Cell")
table.add_row("Cell", "Cell")
table.box = getattr(box, box_name)
table.title = Text(f"box.{box_name}", style="magenta")
console.print(table)
columns.add_renderable(table)
console.print(columns)
# console.save_html("box.html", inline_styles=True)
console.save_html("box.html", inline_styles=True)

View File

@ -15,7 +15,7 @@ class Columns(JupyterMixin):
"""Display renderables in neat columns.
Args:
renderables (Iterable[RenderableType]): Any number of Rich renderables (including str),
renderables (Iterable[RenderableType]): Any number of Rich renderables (including str).
width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None.
padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1).
expand (bool, optional): Expand columns to full width. Defaults to False.
@ -26,7 +26,7 @@ class Columns(JupyterMixin):
def __init__(
self,
renderables: Iterable[RenderableType],
renderables: Iterable[RenderableType] = None,
padding: PaddingDimensions = (0, 1),
width: int = None,
expand: bool = False,
@ -34,7 +34,7 @@ class Columns(JupyterMixin):
column_first: bool = False,
right_to_left: bool = False,
) -> None:
self.renderables = list(renderables)
self.renderables = list(renderables or [])
self.width = width
self.padding = padding
self.expand = expand
@ -42,6 +42,14 @@ class Columns(JupyterMixin):
self.column_first = column_first
self.right_to_left = right_to_left
def add_renderable(self, renderable: RenderableType) -> None:
"""Add a renderable to the columns.
Args:
renderable (RenderableType): Any renderable object.
"""
self.renderables.append(renderable)
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:

View File

@ -112,6 +112,7 @@ class Table(JupyterMixin):
border_style (Union[str, Style], optional): Style of the border. Defaults to None.
title_style (Union[str, Style], optional): Style of the title. Defaults to None.
caption_style (Union[str, Style], optional): Style of the caption. Defaults to None.
safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.
"""
columns: List[Column]
@ -138,6 +139,7 @@ class Table(JupyterMixin):
border_style: StyleType = None,
title_style: StyleType = None,
caption_style: StyleType = None,
safe_box: bool = True,
) -> None:
self.columns = [
@ -162,6 +164,7 @@ class Table(JupyterMixin):
self.border_style = border_style
self.title_style = title_style
self.caption_style = title_style
self.safe_box = safe_box
self._row_count = 0
self.row_styles = list(row_styles or [])
@ -481,11 +484,11 @@ class Table(JupyterMixin):
for first, last, (style, renderable) in loop_first_last(raw_cells):
yield _Cell(style, add_padding(renderable, first, last))
def _get_padding_width(self, column_index) -> int:
def _get_padding_width(self, column_index: int) -> int:
"""Get extra width from padding."""
_, pad_right, _, pad_left = self.padding
if self.collapse_padding:
if column_index != 0:
if column_index > 0:
pad_left = max(0, pad_right - pad_left)
return pad_left + pad_right
@ -537,6 +540,9 @@ class Table(JupyterMixin):
if isinstance(self.box, box.PlatformDefaultBox)
else self.box
)
if self.safe_box and _box is not None and console.legacy_windows:
_box = box.LEGACY_WINDOWS_SUBSTITUTIONS.get(_box, _box)
# _box = self.box
new_line = Segment.line()

View File

@ -25,7 +25,6 @@ COLUMN_DATA = [
"Anteater, australian spiny",
"Tachyglossus aculeatus",
"Anteater, giant",
"Myrmecophaga tridactyla",
]
@ -36,6 +35,7 @@ def render():
empty_columns = Columns([])
console.print(empty_columns)
columns = Columns(COLUMN_DATA)
columns.add_renderable("Myrmecophaga tridactyla")
console.rule("optimal")
console.print(columns)
console.rule("optimal, expand")