Aluode/PerceptionLabPortable
0
1from typing import Union2 3from .align import AlignMethod4from .cells import cell_len, set_cell_size5from .console import Console, ConsoleOptions, RenderResult6from .jupyter import JupyterMixin7from .measure import Measurement8from .style import Style9from .text import Text10 11 12class Rule(JupyterMixin):13 """A console renderable to draw a horizontal rule (line).14 15 Args:16 title (Union[str, Text], optional): Text to render in the rule. Defaults to "".17 characters (str, optional): Character(s) used to draw the line. Defaults to "─".18 style (StyleType, optional): Style of Rule. Defaults to "rule.line".19 end (str, optional): Character at end of Rule. defaults to "\\\\n"20 align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center".21 """22 23 def __init__(24 self,25 title: Union[str, Text] = "",26 *,27 characters: str = "─",28 style: Union[str, Style] = "rule.line",29 end: str = "\n",30 align: AlignMethod = "center",31 ) -> None:32 if cell_len(characters) < 1:33 raise ValueError(34 "'characters' argument must have a cell width of at least 1"35 )36 if align not in ("left", "center", "right"):37 raise ValueError(38 f'invalid value for align, expected "left", "center", "right" (not {align!r})'39 )40 self.title = title41 self.characters = characters42 self.style = style43 self.end = end44 self.align = align45 46 def __repr__(self) -> str:47 return f"Rule({self.title!r}, {self.characters!r})"48 49 def __rich_console__(50 self, console: Console, options: ConsoleOptions51 ) -> RenderResult:52 width = options.max_width53 54 characters = (55 "-"56 if (options.ascii_only and not self.characters.isascii())57 else self.characters58 )59 60 chars_len = cell_len(characters)61 if not self.title:62 yield self._rule_line(chars_len, width)63 return64 65 if isinstance(self.title, Text):66 title_text = self.title67 else:68 title_text = console.render_str(self.title, style="rule.text")69 70 title_text.plain = title_text.plain.replace("\n", " ")71 title_text.expand_tabs()72 73 required_space = 4 if self.align == "center" else 274 truncate_width = max(0, width - required_space)75 if not truncate_width:76 yield self._rule_line(chars_len, width)77 return78 79 rule_text = Text(end=self.end)80 if self.align == "center":81 title_text.truncate(truncate_width, overflow="ellipsis")82 side_width = (width - cell_len(title_text.plain)) // 283 left = Text(characters * (side_width // chars_len + 1))84 left.truncate(side_width - 1)85 right_length = width - cell_len(left.plain) - cell_len(title_text.plain)86 right = Text(characters * (side_width // chars_len + 1))87 right.truncate(right_length)88 rule_text.append(left.plain + " ", self.style)89 rule_text.append(title_text)90 rule_text.append(" " + right.plain, self.style)91 elif self.align == "left":92 title_text.truncate(truncate_width, overflow="ellipsis")93 rule_text.append(title_text)94 rule_text.append(" ")95 rule_text.append(characters * (width - rule_text.cell_len), self.style)96 elif self.align == "right":97 title_text.truncate(truncate_width, overflow="ellipsis")98 rule_text.append(characters * (width - title_text.cell_len - 1), self.style)99 rule_text.append(" ")100 rule_text.append(title_text)101 102 rule_text.plain = set_cell_size(rule_text.plain, width)103 yield rule_text104 105 def _rule_line(self, chars_len: int, width: int) -> Text:106 rule_text = Text(self.characters * ((width // chars_len) + 1), self.style)107 rule_text.truncate(width)108 rule_text.plain = set_cell_size(rule_text.plain, width)109 return rule_text110 111 def __rich_measure__(112 self, console: Console, options: ConsoleOptions113 ) -> Measurement:114 return Measurement(1, 1)115 116 117if __name__ == "__main__": # pragma: no cover118 import sys119 120 from pip._vendor.rich.console import Console121 122 try:123 text = sys.argv[1]124 except IndexError:125 text = "Hello, World"126 console = Console()127 console.print(Rule(title=text))128 129 console = Console()130 console.print(Rule("foo"), width=4)131 