File size: 4,590 Bytes
9c6594c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
from typing import Union
from .align import AlignMethod
from .cells import cell_len, set_cell_size
from .console import Console, ConsoleOptions, RenderResult
from .jupyter import JupyterMixin
from .measure import Measurement
from .style import Style
from .text import Text
class Rule(JupyterMixin):
"""A console renderable to draw a horizontal rule (line).
Args:
title (Union[str, Text], optional): Text to render in the rule. Defaults to "".
characters (str, optional): Character(s) used to draw the line. Defaults to "β".
style (StyleType, optional): Style of Rule. Defaults to "rule.line".
end (str, optional): Character at end of Rule. defaults to "\\\\n"
align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center".
"""
def __init__(
self,
title: Union[str, Text] = "",
*,
characters: str = "β",
style: Union[str, Style] = "rule.line",
end: str = "\n",
align: AlignMethod = "center",
) -> None:
if cell_len(characters) < 1:
raise ValueError(
"'characters' argument must have a cell width of at least 1"
)
if align not in ("left", "center", "right"):
raise ValueError(
f'invalid value for align, expected "left", "center", "right" (not {align!r})'
)
self.title = title
self.characters = characters
self.style = style
self.end = end
self.align = align
def __repr__(self) -> str:
return f"Rule({self.title!r}, {self.characters!r})"
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
width = options.max_width
characters = (
"-"
if (options.ascii_only and not self.characters.isascii())
else self.characters
)
chars_len = cell_len(characters)
if not self.title:
yield self._rule_line(chars_len, width)
return
if isinstance(self.title, Text):
title_text = self.title
else:
title_text = console.render_str(self.title, style="rule.text")
title_text.plain = title_text.plain.replace("\n", " ")
title_text.expand_tabs()
required_space = 4 if self.align == "center" else 2
truncate_width = max(0, width - required_space)
if not truncate_width:
yield self._rule_line(chars_len, width)
return
rule_text = Text(end=self.end)
if self.align == "center":
title_text.truncate(truncate_width, overflow="ellipsis")
side_width = (width - cell_len(title_text.plain)) // 2
left = Text(characters * (side_width // chars_len + 1))
left.truncate(side_width - 1)
right_length = width - cell_len(left.plain) - cell_len(title_text.plain)
right = Text(characters * (side_width // chars_len + 1))
right.truncate(right_length)
rule_text.append(left.plain + " ", self.style)
rule_text.append(title_text)
rule_text.append(" " + right.plain, self.style)
elif self.align == "left":
title_text.truncate(truncate_width, overflow="ellipsis")
rule_text.append(title_text)
rule_text.append(" ")
rule_text.append(characters * (width - rule_text.cell_len), self.style)
elif self.align == "right":
title_text.truncate(truncate_width, overflow="ellipsis")
rule_text.append(characters * (width - title_text.cell_len - 1), self.style)
rule_text.append(" ")
rule_text.append(title_text)
rule_text.plain = set_cell_size(rule_text.plain, width)
yield rule_text
def _rule_line(self, chars_len: int, width: int) -> Text:
rule_text = Text(self.characters * ((width // chars_len) + 1), self.style)
rule_text.truncate(width)
rule_text.plain = set_cell_size(rule_text.plain, width)
return rule_text
def __rich_measure__(
self, console: Console, options: ConsoleOptions
) -> Measurement:
return Measurement(1, 1)
if __name__ == "__main__": # pragma: no cover
import sys
from rich.console import Console
try:
text = sys.argv[1]
except IndexError:
text = "Hello, World"
console = Console()
console.print(Rule(title=text))
console = Console()
console.print(Rule("foo"), width=4)
|