From dd5ff93fe9e4945f8cd3f92828a6682fbcee2e1a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 15:04:19 +0100 Subject: [PATCH 01/12] pager functionality --- rich/console.py | 64 +++++++++++++++++++++++++++++++++++++++++++++---- rich/pager.py | 31 ++++++++++++++++++++++++ rich/segment.py | 24 +++++++++++++++++++ rich/style.py | 7 +++--- 4 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 rich/pager.py diff --git a/rich/console.py b/rich/console.py index f9f7ba80..375a6b8d 100644 --- a/rich/console.py +++ b/rich/console.py @@ -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: diff --git a/rich/pager.py b/rich/pager.py new file mode 100644 index 00000000..c1aa5b23 --- /dev/null +++ b/rich/pager.py @@ -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()) diff --git a/rich/segment.py b/rich/segment.py index 21c91321..a63e2534 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -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")]] diff --git a/rich/style.py b/rich/style.py index a67e2c67..707324a9 100644 --- a/rich/style.py +++ b/rich/style.py @@ -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 From 44afdff5231f96199ce344a022e532b8b4a24ddc Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 15:13:51 +0100 Subject: [PATCH 02/12] test fixes --- rich/console.py | 2 +- rich/pager.py | 2 +- rich/segment.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rich/console.py b/rich/console.py index 375a6b8d..900c8c8a 100644 --- a/rich/console.py +++ b/rich/console.py @@ -557,7 +557,7 @@ class Console: Returns: str: Console output. """ - render_result = self._render_buffer() + render_result = self._render_buffer(self._buffer) del self._buffer[:] self._exit_buffer() return render_result diff --git a/rich/pager.py b/rich/pager.py index c1aa5b23..0954c0fc 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -14,7 +14,7 @@ class Pager(ABC): """ -class SystemPager: +class SystemPager(Pager): """Uses the pager installed on the system.""" def show(self, content: str) -> None: diff --git a/rich/segment.py b/rich/segment.py index a63e2534..26ee041d 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -312,7 +312,7 @@ class Segment(NamedTuple): yield segment else: text, style, _is_control = segment - yield cls(text, style.copy(link=None)) + yield cls(text, style.copy(link=None) if style else None) @classmethod def strip_styles(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: From 327d642b844f51cbcf5b5900adf9fb37ccac8129 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 17:11:33 +0100 Subject: [PATCH 03/12] docs --- CHANGELOG.md | 1 + docs/source/console.rst | 19 +++++++++++++++++++ rich/pager.py | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7854b3e..f813ffeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added ascii_only to ConsoleOptions - Addded box.SQUARE_DOUBLE_HEAD - Added highlighting of EUI-48 and EUI-64 (MAC addresses) +- Added Console.pager ### Changed diff --git a/docs/source/console.rst b/docs/source/console.rst index 5d8d824f..abb863c1 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -210,6 +210,25 @@ An alternative way of capturing output is to set the Console file to a :py:class console.print("[bold red]Hello[/] World") str_output = console.file.getvalue() +Paging +------ + +If you have some long output to present to the user you can use a *pager* to display it. A pager is typically an application defined by your operating system which will at least support pressing a key to scroll, but will often support scroll up and down through the text. + +You can page output from a Console by calling :meth:`~rich.console.Console.pager` which returns a context manger. When the pager exits, anything that was printed will be sent to the pager. Here's an example:: + + from rich.__main__ import make_test_card + from rich.console import Console + + console = Console() + with console.pager(): + console.print(make_test_card()) + +Since the default pager on most platforms don't support color, Rich will strip color from the output. If you know that your pager supports color, you can set ``style=True`` when calling the :meth:`~rich.console.Console.pager` method. + +.. note:: + Rich will use the ``PAGER`` environment variable to get the pager command. On Linux and macOS you can set this to ``less -r`` to enable paging with ANSI styles. + Terminal detection ------------------ diff --git a/rich/pager.py b/rich/pager.py index 0954c0fc..06f51372 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -27,5 +27,5 @@ if __name__ == "__main__": # pragma: no cover from .console import Console console = Console() - with console.pager(): + with console.pager(styles=True): console.print(make_test_card()) From a236d8fd6308933141899fd11cc1adf48ab7dec9 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:12:44 +0100 Subject: [PATCH 04/12] add tests for style --- rich/segment.py | 2 +- rich/style.py | 29 +++++++++++++++++++++++++---- tests/test_segment.py | 10 ++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/rich/segment.py b/rich/segment.py index 26ee041d..3222f3d2 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -312,7 +312,7 @@ class Segment(NamedTuple): yield segment else: text, style, _is_control = segment - yield cls(text, style.copy(link=None) if style else None) + yield cls(text, style.update_link(None) if style else None) @classmethod def strip_styles(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: diff --git a/rich/style.py b/rich/style.py index 707324a9..4eca6361 100644 --- a/rich/style.py +++ b/rich/style.py @@ -501,7 +501,7 @@ class Style: iter_styles = iter(styles) return sum(iter_styles, next(iter_styles)) - def copy(self, link: str = None) -> "Style": + def copy(self) -> "Style": """Get a copy of this style. Returns: @@ -516,9 +516,30 @@ class Style: style._bgcolor = self._bgcolor style._attributes = self._attributes style._set_attributes = self._set_attributes - _link = self._link if link is None else link - style._link = _link - style._link_id = f"{time()}-{randint(0, 999999)}" if _link else "" + style._link = self._link + style._link_id = f"{time()}-{randint(0, 999999)}" if self._link else "" + style._hash = self._hash + style._null = False + return style + + def update_link(self, link: str = None) -> "Style": + """Get a copy with a different value for link. + + Args: + link (str, optional): New value for link. Defaults to None. + + Returns: + Style: A new Style instance. + """ + style = self.__new__(Style) + style._ansi = self._ansi + style._style_definition = self._style_definition + style._color = self._color + style._bgcolor = self._bgcolor + style._attributes = self._attributes + style._set_attributes = self._set_attributes + style._link = link + style._link_id = f"{time()}-{randint(0, 999999)}" if link else "" style._hash = self._hash style._null = False return style diff --git a/tests/test_segment.py b/tests/test_segment.py index c5e24995..04e01ad8 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -86,3 +86,13 @@ def test_filter_control(): assert list(Segment.filter_control(segments, is_control=True)) == [ Segment("bar", is_control=True) ] + + +def test_strip_styles(): + segments = [Segment("foo", Style(bold=True))] + assert list(Segment.strip_styles(segments)) == [Segment("foo", None)] + + +def test_strip_links(): + segments = [Segment("foo", Style(bold=True, link="https://www.example.org"))] + assert list(Segment.strip_links(segments)) == [Segment("foo", Style(bold=True))] \ No newline at end of file From 4310bc8ae8cc41763b382c3a52dc341296c89e69 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:16:09 +0100 Subject: [PATCH 05/12] add tests for style --- rich/pager.py | 4 +++- tests/test_console.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/rich/pager.py b/rich/pager.py index 06f51372..a17b6bc3 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -17,9 +17,11 @@ class Pager(ABC): class SystemPager(Pager): """Uses the pager installed on the system.""" + _pager = pydoc.pager + def show(self, content: str) -> None: """Use the same pager used by pydoc.""" - pydoc.pager(content) + self._pager(content) if __name__ == "__main__": # pragma: no cover diff --git a/tests/test_console.py b/tests/test_console.py index 3df8e7ce..153658d1 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -2,12 +2,14 @@ import io import os import sys import tempfile +from threading import setprofile import pytest from rich.color import ColorSystem from rich.console import CaptureError, Console, ConsoleOptions from rich import errors +from rich.pager import SystemPager from rich.panel import Panel from rich.style import Style @@ -346,3 +348,21 @@ def test_bell() -> None: console.begin_capture() console.bell() assert console.end_capture() == "\x07" + + +def test_pager() -> None: + console = Console() + + pager_called = False + + def mock_pager(content: str) -> None: + nonlocal pager_called + pager_called = True + + pager = SystemPager() + pager._pager = dummy_pager + + with console.pager(pager): + console.print("Hello World") + + assert pager_called \ No newline at end of file From f4b3c8a2abfc5a4eb6a9c57b67b28527df5bb61c Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:20:23 +0100 Subject: [PATCH 06/12] pager tests --- tests/test_console.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/test_console.py b/tests/test_console.py index 153658d1..dbdec9be 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -3,6 +3,7 @@ import os import sys import tempfile from threading import setprofile +from typing import Optional import pytest @@ -353,16 +354,20 @@ def test_bell() -> None: def test_pager() -> None: console = Console() - pager_called = False + pager_content: Optional[str] = None def mock_pager(content: str) -> None: - nonlocal pager_called - pager_called = True + nonlocal pager_content + pager_content = content pager = SystemPager() - pager._pager = dummy_pager + pager._pager = mock_pager with console.pager(pager): - console.print("Hello World") + console.print("[bold]Hello World") + assert pager_content == "Hello World\n" - assert pager_called \ No newline at end of file + with console.pager(pager, styles=True, links=False): + console.print("[bold link https:/example.org]Hello World") + + assert pager_content == "Hello World\n" \ No newline at end of file From 6ce51f3ca1c700dc7efeda46603cbee92e6c2142 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:37:40 +0100 Subject: [PATCH 07/12] fix --- rich/pager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/pager.py b/rich/pager.py index a17b6bc3..52e77ef6 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -17,7 +17,7 @@ class Pager(ABC): class SystemPager(Pager): """Uses the pager installed on the system.""" - _pager = pydoc.pager + _pager = lambda self, content: pydoc.pager(content) def show(self, content: str) -> None: """Use the same pager used by pydoc.""" From 436e3005733296f07968a29cef1bf4d81274eac7 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:39:50 +0100 Subject: [PATCH 08/12] blackify --- tests/test_console.py | 2 +- tests/test_segment.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_console.py b/tests/test_console.py index dbdec9be..17ea469b 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -370,4 +370,4 @@ def test_pager() -> None: with console.pager(pager, styles=True, links=False): console.print("[bold link https:/example.org]Hello World") - assert pager_content == "Hello World\n" \ No newline at end of file + assert pager_content == "Hello World\n" diff --git a/tests/test_segment.py b/tests/test_segment.py index 04e01ad8..2c3344dd 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -95,4 +95,4 @@ def test_strip_styles(): def test_strip_links(): segments = [Segment("foo", Style(bold=True, link="https://www.example.org"))] - assert list(Segment.strip_links(segments)) == [Segment("foo", Style(bold=True))] \ No newline at end of file + assert list(Segment.strip_links(segments)) == [Segment("foo", Style(bold=True))] From dd4a1d6c3a5a2e0693c75e4344d3806b87d8dc00 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 10 Oct 2020 18:52:50 +0100 Subject: [PATCH 09/12] imports --- tests/test_console.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_console.py b/tests/test_console.py index 17ea469b..eca30009 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -2,14 +2,13 @@ import io import os import sys import tempfile -from threading import setprofile from typing import Optional import pytest +from rich import errors from rich.color import ColorSystem from rich.console import CaptureError, Console, ConsoleOptions -from rich import errors from rich.pager import SystemPager from rich.panel import Panel from rich.style import Style From 2d554fb5ae66c53eef9babc8a9132f2e191695f0 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 11 Oct 2020 12:54:20 +0100 Subject: [PATCH 10/12] remove pager ABC --- rich/console.py | 15 ++++++--------- rich/pager.py | 14 +------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/rich/console.py b/rich/console.py index 900c8c8a..eabf2323 100644 --- a/rich/console.py +++ b/rich/console.py @@ -35,7 +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 .pager import SystemPager from .pretty import Pretty from .scope import render_scope from .segment import Segment @@ -212,12 +212,10 @@ class PagerContext: 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 @@ -236,7 +234,9 @@ class PagerContext: elif not self.links: segments = Segment.strip_links(segments) content = self._console._render_buffer(segments) - self.pager.show(content) + pager = SystemPager() + pager.show(content) + self._console._exit_buffer() class RenderGroup: @@ -701,14 +701,11 @@ class Console: capture = Capture(self) return capture - def pager( - self, pager: Pager = None, styles: bool = False, links: bool = False - ) -> PagerContext: + def pager(self, 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. @@ -722,7 +719,7 @@ class Console: Returns: PagerContext: A context manager. """ - return PagerContext(self, pager=pager, styles=styles, links=links) + return PagerContext(self, styles=styles, links=links) def line(self, count: int = 1) -> None: """Write new line(s). diff --git a/rich/pager.py b/rich/pager.py index 52e77ef6..69023bda 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -2,19 +2,7 @@ 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(Pager): +class SystemPager: """Uses the pager installed on the system.""" _pager = lambda self, content: pydoc.pager(content) From 5ed34b19547517be80366c1dd4ed0563b609310d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 11 Oct 2020 15:35:07 +0100 Subject: [PATCH 11/12] pager fix --- rich/console.py | 14 +++++++++----- rich/pager.py | 14 +++++++++++++- rich/table.py | 8 +------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/rich/console.py b/rich/console.py index eabf2323..64d01092 100644 --- a/rich/console.py +++ b/rich/console.py @@ -35,7 +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 SystemPager +from .pager import Pager, SystemPager from .pretty import Pretty from .scope import render_scope from .segment import Segment @@ -212,10 +212,12 @@ class PagerContext: 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 @@ -234,8 +236,7 @@ class PagerContext: elif not self.links: segments = Segment.strip_links(segments) content = self._console._render_buffer(segments) - pager = SystemPager() - pager.show(content) + self.pager.show(content) self._console._exit_buffer() @@ -701,11 +702,14 @@ class Console: capture = Capture(self) return capture - def pager(self, styles: bool = False, links: bool = False) -> PagerContext: + 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. @@ -719,7 +723,7 @@ class Console: Returns: PagerContext: A context manager. """ - return PagerContext(self, styles=styles, links=links) + return PagerContext(self, pager=pager, styles=styles, links=links) def line(self, count: int = 1) -> None: """Write new line(s). diff --git a/rich/pager.py b/rich/pager.py index 69023bda..52e77ef6 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -2,7 +2,19 @@ from abc import ABC, abstractmethod import pydoc -class SystemPager: +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(Pager): """Uses the pager installed on the system.""" _pager = lambda self, content: pydoc.pager(content) diff --git a/rich/table.py b/rich/table.py index 0ff4c49d..1745d700 100644 --- a/rich/table.py +++ b/rich/table.py @@ -171,7 +171,7 @@ class Table(JupyterMixin): self.footer_style = footer_style self.border_style = border_style self.title_style = title_style - self.caption_style = title_style + self.caption_style = caption_style self.title_justify = title_justify self.caption_justify = caption_justify self._row_count = 0 @@ -241,12 +241,6 @@ class Table(JupyterMixin): def __rich_measure__(self, console: "Console", max_width: int) -> Measurement: if self.width is not None: max_width = self.width - - # if self.box: - # max_width -= len(self.columns) - 1 - # if self.show_edge: - # max_width -= 2 - if max_width < 0: return Measurement(0, 0) From e11800a2889fa35228bd22b0121f42cd6e856976 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 11 Oct 2020 15:38:04 +0100 Subject: [PATCH 12/12] docs --- docs/source/console.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index abb863c1..a3c690c7 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -213,7 +213,7 @@ An alternative way of capturing output is to set the Console file to a :py:class Paging ------ -If you have some long output to present to the user you can use a *pager* to display it. A pager is typically an application defined by your operating system which will at least support pressing a key to scroll, but will often support scroll up and down through the text. +If you have some long output to present to the user you can use a *pager* to display it. A pager is typically an application on by your operating system which will at least support pressing a key to scroll, but will often support scrolling up and down through the text and other features. You can page output from a Console by calling :meth:`~rich.console.Console.pager` which returns a context manger. When the pager exits, anything that was printed will be sent to the pager. Here's an example::