This commit is contained in:
Samuel Colvin 2025-06-13 12:14:14 -03:00 committed by GitHub
commit ee5925241e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 55 additions and 5 deletions

View file

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- Allow a custom message with a `Live` overflows, instead of an ellipsis. https://github.com/Textualize/rich/pull/3702
## [14.0.0] - 2025-03-30
### Added

View file

@ -92,3 +92,4 @@ The following people have contributed to the development of Rich:
- [chthollyphile](https://github.com/chthollyphile)
- [Jonathan Helmus](https://github.com/jjhelmus)
- [Brandon Capener](https://github.com/bcapener)
- [Samuel Colvin](https://github.com/samuelcolvin)

View file

@ -1,7 +1,19 @@
import sys
from threading import Event, RLock, Thread
from types import TracebackType
from typing import IO, Any, Callable, List, Optional, TextIO, Type, cast
from typing import (
IO,
Any,
Callable,
List,
Literal,
Optional,
TextIO,
Tuple,
Type,
Union,
cast,
)
from . import get_console
from .console import Console, ConsoleRenderable, RenderableType, RenderHook
@ -44,7 +56,7 @@ class Live(JupyterMixin, RenderHook):
transient (bool, optional): Clear the renderable on exit (has no effect when screen=True). Defaults to False.
redirect_stdout (bool, optional): Enable redirection of stdout, so ``print`` may be used. Defaults to True.
redirect_stderr (bool, optional): Enable redirection of stderr. Defaults to True.
vertical_overflow (VerticalOverflowMethod, optional): How to handle renderable when it is too tall for the console. Defaults to "ellipsis".
vertical_overflow (VerticalOverflowMethod, optional): How to handle renderable when it is too tall for the console, pass `("ellipsis", "message ...")` for a custom message on overflow. Defaults to "ellipsis".
get_renderable (Callable[[], RenderableType], optional): Optional callable to get renderable. Defaults to None.
"""
@ -59,7 +71,9 @@ class Live(JupyterMixin, RenderHook):
transient: bool = False,
redirect_stdout: bool = True,
redirect_stderr: bool = True,
vertical_overflow: VerticalOverflowMethod = "ellipsis",
vertical_overflow: Union[
VerticalOverflowMethod, Tuple[Literal["ellipsis"], str]
] = "ellipsis",
get_renderable: Optional[Callable[[], RenderableType]] = None,
) -> None:
assert refresh_per_second > 0, "refresh_per_second must be > 0"
@ -82,10 +96,18 @@ class Live(JupyterMixin, RenderHook):
self._refresh_thread: Optional[_RefreshThread] = None
self.refresh_per_second = refresh_per_second
if isinstance(vertical_overflow, tuple):
vertical_overflow, vertical_overflow_message = vertical_overflow
else:
vertical_overflow_message = "..."
self.vertical_overflow = vertical_overflow
self.vertical_overflow_message = vertical_overflow_message
self._get_renderable = get_renderable
self._live_render = LiveRender(
self.get_renderable(), vertical_overflow=vertical_overflow
self.get_renderable(),
vertical_overflow=vertical_overflow,
vertical_overflow_message=vertical_overflow_message,
)
@property

View file

@ -30,10 +30,12 @@ class LiveRender:
renderable: RenderableType,
style: StyleType = "",
vertical_overflow: VerticalOverflowMethod = "ellipsis",
vertical_overflow_message: str = "...",
) -> None:
self.renderable = renderable
self.style = style
self.vertical_overflow = vertical_overflow
self.vertical_overflow_message = vertical_overflow_message
self._shape: Optional[Tuple[int, int]] = None
def set_renderable(self, renderable: RenderableType) -> None:
@ -95,7 +97,7 @@ class LiveRender:
elif self.vertical_overflow == "ellipsis":
lines = lines[: (options.size.height - 1)]
overflow_text = Text(
"...",
self.vertical_overflow_message,
overflow="crop",
justify="center",
end="",

View file

@ -83,6 +83,25 @@ def test_growing_display_overflow_ellipsis() -> None:
)
def test_growing_display_overflow_ellipsis_message() -> None:
console = create_capture_console(height=3)
console.begin_capture()
with Live(
console=console,
auto_refresh=False,
vertical_overflow=("ellipsis", "custom msg"),
) as live:
display = ""
for step in range(5):
display += f"Step {step}\n"
live.update(display, refresh=True)
output = console.end_capture()
assert (
output
== "\x1b[?25lStep 0\n\r\x1b[2K\x1b[1A\x1b[2KStep 0\nStep 1\n\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2KStep 0\nStep 1\n custom msg \r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2KStep 0\nStep 1\n custom msg \r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2KStep 0\nStep 1\n custom msg \r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2KStep 0\nStep 1\nStep 2\nStep 3\nStep 4\n\n\x1b[?25h"
)
def test_growing_display_overflow_crop() -> None:
console = create_capture_console(height=5)
console.begin_capture()