mirror of
https://github.com/Textualize/rich.git
synced 2025-08-04 18:18:22 +00:00
Merge 01bc82ac7a
into c8f234f136
This commit is contained in:
commit
ee5925241e
5 changed files with 55 additions and 5 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
30
rich/live.py
30
rich/live.py
|
@ -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
|
||||
|
|
|
@ -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="",
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue