Spaces:
Sleeping
Sleeping
import sys | |
from typing import Optional, Tuple | |
if sys.version_info >= (3, 8): | |
from typing import Literal | |
else: | |
from pip._vendor.typing_extensions import Literal # pragma: no cover | |
from ._loop import loop_last | |
from .console import Console, ConsoleOptions, RenderableType, RenderResult | |
from .control import Control | |
from .segment import ControlType, Segment | |
from .style import StyleType | |
from .text import Text | |
VerticalOverflowMethod = Literal["crop", "ellipsis", "visible"] | |
class LiveRender: | |
"""Creates a renderable that may be updated. | |
Args: | |
renderable (RenderableType): Any renderable object. | |
style (StyleType, optional): An optional style to apply to the renderable. Defaults to "". | |
""" | |
def __init__( | |
self, | |
renderable: RenderableType, | |
style: StyleType = "", | |
vertical_overflow: VerticalOverflowMethod = "ellipsis", | |
) -> None: | |
self.renderable = renderable | |
self.style = style | |
self.vertical_overflow = vertical_overflow | |
self._shape: Optional[Tuple[int, int]] = None | |
def set_renderable(self, renderable: RenderableType) -> None: | |
"""Set a new renderable. | |
Args: | |
renderable (RenderableType): Any renderable object, including str. | |
""" | |
self.renderable = renderable | |
def position_cursor(self) -> Control: | |
"""Get control codes to move cursor to beginning of live render. | |
Returns: | |
Control: A control instance that may be printed. | |
""" | |
if self._shape is not None: | |
_, height = self._shape | |
return Control( | |
ControlType.CARRIAGE_RETURN, | |
(ControlType.ERASE_IN_LINE, 2), | |
*( | |
( | |
(ControlType.CURSOR_UP, 1), | |
(ControlType.ERASE_IN_LINE, 2), | |
) | |
* (height - 1) | |
) | |
) | |
return Control() | |
def restore_cursor(self) -> Control: | |
"""Get control codes to clear the render and restore the cursor to its previous position. | |
Returns: | |
Control: A Control instance that may be printed. | |
""" | |
if self._shape is not None: | |
_, height = self._shape | |
return Control( | |
ControlType.CARRIAGE_RETURN, | |
*((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height | |
) | |
return Control() | |
def __rich_console__( | |
self, console: Console, options: ConsoleOptions | |
) -> RenderResult: | |
renderable = self.renderable | |
style = console.get_style(self.style) | |
lines = console.render_lines(renderable, options, style=style, pad=False) | |
shape = Segment.get_shape(lines) | |
_, height = shape | |
if height > options.size.height: | |
if self.vertical_overflow == "crop": | |
lines = lines[: options.size.height] | |
shape = Segment.get_shape(lines) | |
elif self.vertical_overflow == "ellipsis": | |
lines = lines[: (options.size.height - 1)] | |
overflow_text = Text( | |
"...", | |
overflow="crop", | |
justify="center", | |
end="", | |
style="live.ellipsis", | |
) | |
lines.append(list(console.render(overflow_text))) | |
shape = Segment.get_shape(lines) | |
self._shape = shape | |
new_line = Segment.line() | |
for last, line in loop_last(lines): | |
yield from line | |
if not last: | |
yield new_line | |