rule.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from typing import Union
  2. from .align import AlignMethod
  3. from .cells import cell_len, set_cell_size
  4. from .console import Console, ConsoleOptions, RenderResult
  5. from .jupyter import JupyterMixin
  6. from .style import Style
  7. from .text import Text
  8. class Rule(JupyterMixin):
  9. """A console renderable to draw a horizontal rule (line).
  10. Args:
  11. title (Union[str, Text], optional): Text to render in the rule. Defaults to "".
  12. characters (str, optional): Character(s) used to draw the line. Defaults to "─".
  13. style (StyleType, optional): Style of Rule. Defaults to "rule.line".
  14. end (str, optional): Character at end of Rule. defaults to "\\\\n"
  15. align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center".
  16. """
  17. def __init__(
  18. self,
  19. title: Union[str, Text] = "",
  20. *,
  21. characters: str = "─",
  22. style: Union[str, Style] = "rule.line",
  23. end: str = "\n",
  24. align: AlignMethod = "center",
  25. ) -> None:
  26. if cell_len(characters) < 1:
  27. raise ValueError(
  28. "'characters' argument must have a cell width of at least 1"
  29. )
  30. if align not in ("left", "center", "right"):
  31. raise ValueError(
  32. f'invalid value for align, expected "left", "center", "right" (not {align!r})'
  33. )
  34. self.title = title
  35. self.characters = characters
  36. self.style = style
  37. self.end = end
  38. self.align = align
  39. def __repr__(self) -> str:
  40. return f"Rule({self.title!r}, {self.characters!r})"
  41. def __rich_console__(
  42. self, console: Console, options: ConsoleOptions
  43. ) -> RenderResult:
  44. width = options.max_width
  45. # Python3.6 doesn't have an isascii method on str
  46. isascii = getattr(str, "isascii", None) or (
  47. lambda s: all(ord(c) < 128 for c in s)
  48. )
  49. characters = (
  50. "-"
  51. if (options.ascii_only and not isascii(self.characters))
  52. else self.characters
  53. )
  54. chars_len = cell_len(characters)
  55. if not self.title:
  56. rule_text = Text(characters * ((width // chars_len) + 1), self.style)
  57. rule_text.truncate(width)
  58. rule_text.plain = set_cell_size(rule_text.plain, width)
  59. yield rule_text
  60. return
  61. if isinstance(self.title, Text):
  62. title_text = self.title
  63. else:
  64. title_text = console.render_str(self.title, style="rule.text")
  65. title_text.plain = title_text.plain.replace("\n", " ")
  66. title_text.expand_tabs()
  67. rule_text = Text(end=self.end)
  68. if self.align == "center":
  69. title_text.truncate(width - 4, overflow="ellipsis")
  70. side_width = (width - cell_len(title_text.plain)) // 2
  71. left = Text(characters * (side_width // chars_len + 1))
  72. left.truncate(side_width - 1)
  73. right_length = width - cell_len(left.plain) - cell_len(title_text.plain)
  74. right = Text(characters * (side_width // chars_len + 1))
  75. right.truncate(right_length)
  76. rule_text.append(left.plain + " ", self.style)
  77. rule_text.append(title_text)
  78. rule_text.append(" " + right.plain, self.style)
  79. elif self.align == "left":
  80. title_text.truncate(width - 2, overflow="ellipsis")
  81. rule_text.append(title_text)
  82. rule_text.append(" ")
  83. rule_text.append(characters * (width - rule_text.cell_len), self.style)
  84. elif self.align == "right":
  85. title_text.truncate(width - 2, overflow="ellipsis")
  86. rule_text.append(characters * (width - title_text.cell_len - 1), self.style)
  87. rule_text.append(" ")
  88. rule_text.append(title_text)
  89. rule_text.plain = set_cell_size(rule_text.plain, width)
  90. yield rule_text
  91. if __name__ == "__main__": # pragma: no cover
  92. from pip._vendor.rich.console import Console
  93. import sys
  94. try:
  95. text = sys.argv[1]
  96. except IndexError:
  97. text = "Hello, World"
  98. console = Console()
  99. console.print(Rule(title=text))