mirror of https://github.com/Textualize/rich.git
pager functionality
This commit is contained in:
parent
af7fbf9a2e
commit
dd5ff93fe9
|
@ -35,6 +35,7 @@ from .control import Control
|
|||
from .highlighter import NullHighlighter, ReprHighlighter
|
||||
from .markup import render as render_markup
|
||||
from .measure import Measurement, measure_renderables
|
||||
from .pager import Pager, SystemPager
|
||||
from .pretty import Pretty
|
||||
from .scope import render_scope
|
||||
from .segment import Segment
|
||||
|
@ -205,6 +206,39 @@ class ThemeContext:
|
|||
self.console.pop_theme()
|
||||
|
||||
|
||||
class PagerContext:
|
||||
"""A context manager that 'pages' content. See :meth:`~rich.console.Console.pager` for usage."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
console: "Console",
|
||||
pager: Pager = None,
|
||||
styles: bool = False,
|
||||
links: bool = False,
|
||||
) -> None:
|
||||
self._console = console
|
||||
self.pager = SystemPager() if pager is None else pager
|
||||
self.styles = styles
|
||||
self.links = links
|
||||
|
||||
def __enter__(self) -> "PagerContext":
|
||||
self._console._enter_buffer()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
||||
if exc_type is None:
|
||||
with self._console._lock:
|
||||
buffer: List[Segment] = self._console._buffer[:]
|
||||
del self._console._buffer[:]
|
||||
segments: Iterable[Segment] = buffer
|
||||
if not self.styles:
|
||||
segments = Segment.strip_styles(segments)
|
||||
elif not self.links:
|
||||
segments = Segment.strip_links(segments)
|
||||
content = self._console._render_buffer(segments)
|
||||
self.pager.show(content)
|
||||
|
||||
|
||||
class RenderGroup:
|
||||
"""Takes a group of renderables and returns a renderable object that renders the group.
|
||||
|
||||
|
@ -667,6 +701,29 @@ class Console:
|
|||
capture = Capture(self)
|
||||
return capture
|
||||
|
||||
def pager(
|
||||
self, pager: Pager = None, styles: bool = False, links: bool = False
|
||||
) -> PagerContext:
|
||||
"""A context manager to display anything printed within a "pager". The pager used
|
||||
is defined by the system and will typically support at less pressing a key to scroll.
|
||||
|
||||
Args:
|
||||
pager (Pager, optional): A pager object, or None to use :class:~rich.pager.SystemPager`. Defaults to None.
|
||||
styles (bool, optional): Show styles in pager. Defaults to False.
|
||||
links (bool, optional): Show links in pager. Defaults to False.
|
||||
|
||||
Example:
|
||||
>>> from rich.console import Console
|
||||
>>> from rich.__main__ import make_test_card
|
||||
>>> console = Console()
|
||||
>>> with console.pager():
|
||||
console.print(make_test_card())
|
||||
|
||||
Returns:
|
||||
PagerContext: A context manager.
|
||||
"""
|
||||
return PagerContext(self, pager=pager, styles=styles, links=links)
|
||||
|
||||
def line(self, count: int = 1) -> None:
|
||||
"""Write new line(s).
|
||||
|
||||
|
@ -1154,7 +1211,8 @@ class Console:
|
|||
display(self._buffer)
|
||||
del self._buffer[:]
|
||||
else:
|
||||
text = self._render_buffer()
|
||||
text = self._render_buffer(self._buffer[:])
|
||||
del self._buffer[:]
|
||||
if text:
|
||||
try:
|
||||
if WINDOWS: # pragma: no cover
|
||||
|
@ -1169,17 +1227,15 @@ class Console:
|
|||
error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***"
|
||||
raise
|
||||
|
||||
def _render_buffer(self) -> str:
|
||||
def _render_buffer(self, buffer: Iterable[Segment]) -> str:
|
||||
"""Render buffered output, and clear buffer."""
|
||||
output: List[str] = []
|
||||
append = output.append
|
||||
color_system = self._color_system
|
||||
legacy_windows = self.legacy_windows
|
||||
buffer = self._buffer[:]
|
||||
if self.record:
|
||||
with self._record_buffer_lock:
|
||||
self._record_buffer.extend(buffer)
|
||||
del self._buffer[:]
|
||||
not_terminal = not self.is_terminal
|
||||
for text, style, is_control in buffer:
|
||||
if style and not is_control:
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
from abc import ABC, abstractmethod
|
||||
import pydoc
|
||||
|
||||
|
||||
class Pager(ABC):
|
||||
"""Base class for a pager."""
|
||||
|
||||
@abstractmethod
|
||||
def show(self, content: str) -> None:
|
||||
"""Show content in pager.
|
||||
|
||||
Args:
|
||||
content (str): Content to be displayed.
|
||||
"""
|
||||
|
||||
|
||||
class SystemPager:
|
||||
"""Uses the pager installed on the system."""
|
||||
|
||||
def show(self, content: str) -> None:
|
||||
"""Use the same pager used by pydoc."""
|
||||
pydoc.pager(content)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
from .__main__ import make_test_card
|
||||
from .console import Console
|
||||
|
||||
console = Console()
|
||||
with console.pager():
|
||||
console.print(make_test_card())
|
|
@ -300,6 +300,30 @@ class Segment(NamedTuple):
|
|||
last_segment = segment
|
||||
yield last_segment
|
||||
|
||||
@classmethod
|
||||
def strip_links(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]:
|
||||
"""Remove all links from an iterable of styles.
|
||||
|
||||
Yields:
|
||||
Segment: Segments with link removed.
|
||||
"""
|
||||
for segment in segments:
|
||||
if segment.is_control or segment.style is None:
|
||||
yield segment
|
||||
else:
|
||||
text, style, _is_control = segment
|
||||
yield cls(text, style.copy(link=None))
|
||||
|
||||
@classmethod
|
||||
def strip_styles(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]:
|
||||
"""Remove all styles from an iterable of segments.
|
||||
|
||||
Yields:
|
||||
Segment: Segments with styles replace with None
|
||||
"""
|
||||
for text, _style, is_control in segments:
|
||||
yield cls(text, None, is_control)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
lines = [[Segment("Hello")]]
|
||||
|
|
|
@ -501,7 +501,7 @@ class Style:
|
|||
iter_styles = iter(styles)
|
||||
return sum(iter_styles, next(iter_styles))
|
||||
|
||||
def copy(self) -> "Style":
|
||||
def copy(self, link: str = None) -> "Style":
|
||||
"""Get a copy of this style.
|
||||
|
||||
Returns:
|
||||
|
@ -516,8 +516,9 @@ class Style:
|
|||
style._bgcolor = self._bgcolor
|
||||
style._attributes = self._attributes
|
||||
style._set_attributes = self._set_attributes
|
||||
style._link = self._link
|
||||
style._link_id = f"{time()}-{randint(0, 999999)}" if self._link else ""
|
||||
_link = self._link if link is None else link
|
||||
style._link = _link
|
||||
style._link_id = f"{time()}-{randint(0, 999999)}" if _link else ""
|
||||
style._hash = self._hash
|
||||
style._null = False
|
||||
return style
|
||||
|
|
Loading…
Reference in New Issue