Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

107 рядки
3.4 KiB

  1. from typing import Optional, Tuple, Literal
  2. from ._loop import loop_last
  3. from .console import Console, ConsoleOptions, RenderableType, RenderResult
  4. from .control import Control
  5. from .segment import ControlType, Segment
  6. from .style import StyleType
  7. from .text import Text
  8. VerticalOverflowMethod = Literal["crop", "ellipsis", "visible"]
  9. class LiveRender:
  10. """Creates a renderable that may be updated.
  11. Args:
  12. renderable (RenderableType): Any renderable object.
  13. style (StyleType, optional): An optional style to apply to the renderable. Defaults to "".
  14. """
  15. def __init__(
  16. self,
  17. renderable: RenderableType,
  18. style: StyleType = "",
  19. vertical_overflow: VerticalOverflowMethod = "ellipsis",
  20. ) -> None:
  21. self.renderable = renderable
  22. self.style = style
  23. self.vertical_overflow = vertical_overflow
  24. self._shape: Optional[Tuple[int, int]] = None
  25. def set_renderable(self, renderable: RenderableType) -> None:
  26. """Set a new renderable.
  27. Args:
  28. renderable (RenderableType): Any renderable object, including str.
  29. """
  30. self.renderable = renderable
  31. def position_cursor(self) -> Control:
  32. """Get control codes to move cursor to beginning of live render.
  33. Returns:
  34. Control: A control instance that may be printed.
  35. """
  36. if self._shape is not None:
  37. _, height = self._shape
  38. return Control(
  39. ControlType.CARRIAGE_RETURN,
  40. (ControlType.ERASE_IN_LINE, 2),
  41. *(
  42. (
  43. (ControlType.CURSOR_UP, 1),
  44. (ControlType.ERASE_IN_LINE, 2),
  45. )
  46. * (height - 1)
  47. )
  48. )
  49. return Control()
  50. def restore_cursor(self) -> Control:
  51. """Get control codes to clear the render and restore the cursor to its previous position.
  52. Returns:
  53. Control: A Control instance that may be printed.
  54. """
  55. if self._shape is not None:
  56. _, height = self._shape
  57. return Control(
  58. ControlType.CARRIAGE_RETURN,
  59. *((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height
  60. )
  61. return Control()
  62. def __rich_console__(
  63. self, console: Console, options: ConsoleOptions
  64. ) -> RenderResult:
  65. renderable = self.renderable
  66. style = console.get_style(self.style)
  67. lines = console.render_lines(renderable, options, style=style, pad=False)
  68. shape = Segment.get_shape(lines)
  69. _, height = shape
  70. if height > options.size.height:
  71. if self.vertical_overflow == "crop":
  72. lines = lines[: options.size.height]
  73. shape = Segment.get_shape(lines)
  74. elif self.vertical_overflow == "ellipsis":
  75. lines = lines[: (options.size.height - 1)]
  76. overflow_text = Text(
  77. "...",
  78. overflow="crop",
  79. justify="center",
  80. end="",
  81. style="live.ellipsis",
  82. )
  83. lines.append(list(console.render(overflow_text)))
  84. shape = Segment.get_shape(lines)
  85. self._shape = shape
  86. new_line = Segment.line()
  87. for last, line in loop_last(lines):
  88. yield from line
  89. if not last:
  90. yield new_line