diff --git a/CHANGELOG.md b/CHANGELOG.md index f986a4d3..e8b8cc98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ 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). +## [1.4.0] - Unreleased + +### Added + +- Added overflow methods +- Added no_wrap option to print() + +### Fixed + +- Improved handling of compressed tables + +### Changed + +- Renamed \_ratio.ratio_divide to \_ratio.ratio_distribute + ## [1.3.1] - 2020-06-01 ### Changed diff --git a/README.md b/README.md index c976671b..b25e38ba 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Rich is a Python library for _rich_ text and beautiful formatting in the terminal. -The [Rich API](https://rich.readthedocs.io/en/latest/) makes it easy to add colorful text (up to 16.7 million colors) with styles (bold, italic, underline etc.) to your script or application. Rich can also render pretty tables, progress bars, markdown, syntax highlighted source code, and tracebacks -- out of the box. +The [Rich API](https://rich.readthedocs.io/en/latest/) makes it easy to add color and style to terminal output. Rich can also render pretty tables, progress bars, markdown, syntax highlighted source code, tracebacks, and more — out of the box. ![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) diff --git a/docs/source/console.rst b/docs/source/console.rst index 8e718617..2353b1da 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -116,6 +116,48 @@ This produces the following output: Rich +Overflow +-------- + +Overflow is what happens when text you print is larger than the available space. Overflow may occur if you print long 'words' such as URLs for instance, or if you have text inside a panel or table cell with restricted space. + +You can specify how Rich should handle overflow with the ``overflow`` argument to :meth:`~rich.console.Console.print` which should be one of the following strings: "fold", "crop", or "ellipsis". The default is "fold" which will put any excess characters on the following line, creating as many new lines as required to fit the text. + +The "crop" method simply truncates the text at the end of the line, discarding any characters that would overflow. + +The "ellipsis" method is similar to "crop", but will insert an ellipsis character ("…") at the end of any text that has been truncated. + +You can specify which overflow method to use with the ``overflow`` argument to :meth:`~rich.console.Console.print`. The following code demonstrates Rich's overflow methods:: + + from typing import List + from rich.console import Console, OverflowMethod + + console = Console(width=14) + supercali = "supercalifragilisticexpialidocious" + + overflow_methods: List[OverflowMethod] = ["fold", "crop", "ellipsis"] + for overflow in overflow_methods: + console.rule(overflow) + console.print(supercali, overflow=overflow, style="bold blue") + console.print() + +This produces the following output: + +.. raw:: html + +
──── fold ──── + supercalifragi + listicexpialid + ocious + + ──── crop ──── + supercalifragi + + ── ellipsis ── + supercalifrag… + ++ Input ----- diff --git a/examples/overflow.py b/examples/overflow.py index 85f57d21..5adaa3db 100644 --- a/examples/overflow.py +++ b/examples/overflow.py @@ -1,11 +1,11 @@ from typing import List from rich.console import Console, OverflowMethod -from rich.text import Text -console = Console() +console = Console(width=14) supercali = "supercalifragilisticexpialidocious" overflow_methods: List[OverflowMethod] = ["fold", "crop", "ellipsis"] for overflow in overflow_methods: console.rule(overflow) - console.print(supercali, overflow=overflow, width=10) + console.print(supercali, overflow=overflow, style="bold blue") + console.print() diff --git a/rich/_ratio.py b/rich/_ratio.py index 5564e749..fe00d5d7 100644 --- a/rich/_ratio.py +++ b/rich/_ratio.py @@ -3,7 +3,6 @@ from math import ceil from typing import List - def ratio_reduce( total: int, ratios: List[int], maximums: List[int], values: List[int] ) -> List[int]: @@ -34,10 +33,10 @@ def ratio_reduce( return result -def ratio_divide( +def ratio_distribute( total: int, ratios: List[int], minimums: List[int] = None ) -> List[int]: - """Divide an integer total in to parts based on ratios. + """Distribute an integer total in to parts based on ratios. Args: total (int): The total to divide. diff --git a/rich/console.py b/rich/console.py index 703c4f72..2ef2f80f 100644 --- a/rich/console.py +++ b/rich/console.py @@ -690,8 +690,6 @@ class Console: highlighter=_highlighter, ) ) - # elif isinstance(renderable, Text): - # append_text(renderable) elif isinstance(renderable, ConsoleRenderable): check_text() append(renderable) @@ -739,6 +737,7 @@ class Console: style: Union[str, Style] = None, justify: JustifyMethod = None, overflow: OverflowMethod = None, + no_wrap: bool = None, emoji: bool = None, markup: bool = None, highlight: bool = None, @@ -753,6 +752,7 @@ class Console: style (Union[str, Style], optional): A style to apply to output. Defaults to None. justify (str, optional): Overflowmethod: "left", "right", "center", or "full". Defaults to ``None``. overflow (str, optional): Overflow method: "crop", "fold", or "ellipisis". Defaults to None. + no_wrap (Optional[bool], optional): Disable wrapping. Defaults to None emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to ``None``. markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to ``None``. highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``. @@ -773,7 +773,7 @@ class Console: highlight=highlight, ) render_options = self.options.update( - justify=justify, overflow=overflow, width=width + justify=justify, overflow=overflow, width=width, no_wrap=no_wrap ) extend = self._buffer.extend render = self.render diff --git a/rich/table.py b/rich/table.py index f66ef3d0..5d017db7 100644 --- a/rich/table.py +++ b/rich/table.py @@ -16,7 +16,7 @@ from typing_extensions import Literal from . import box, errors from ._loop import loop_first, loop_first_last, loop_last -from ._ratio import ratio_divide, ratio_reduce +from ._ratio import ratio_distribute, ratio_reduce from .jupyter import JupyterMixin from .measure import Measurement from .padding import Padding, PaddingDimensions @@ -396,7 +396,7 @@ class Table(JupyterMixin): if column.flexible ] flexible_width = max_width - sum(fixed_widths) - flex_widths = ratio_divide(flexible_width, ratios, flex_minimum) + flex_widths = ratio_distribute(flexible_width, ratios, flex_minimum) iter_flex_widths = iter(flex_widths) for index, column in enumerate(columns): if column.flexible: @@ -433,7 +433,7 @@ class Table(JupyterMixin): table_width = sum(widths) elif table_width < max_width and self.expand: - pad_widths = ratio_divide(max_width - table_width, widths) + pad_widths = ratio_distribute(max_width - table_width, widths) widths = [_width + pad for _width, pad in zip(widths, pad_widths)] return widths diff --git a/tests/test_console.py b/tests/test_console.py index 7bb2e6a9..26d6911d 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -244,3 +244,10 @@ def test_save_html(): console.save_html(export_path) with open(export_path, "rt") as html_file: assert html_file.read() == expected + + +def test_no_wrap(): + console = Console(width=10, file=io.StringIO()) + console.print("X" * 15) + console.print("Y" * 15, no_wrap=True) + assert console.file.getvalue() == "XXXXXXXXXX\nXXXXX\nYYYYYYYYYY\n" diff --git a/tests/test_tools.py b/tests/test_tools.py index f4a077d6..2e6fef7f 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -1,5 +1,5 @@ from rich._loop import loop_first, loop_last, loop_first_last -from rich._ratio import ratio_divide +from rich._ratio import ratio_distribute def test_loop_first(): @@ -29,10 +29,10 @@ def test_loop_first_last(): assert next(iterable) == (False, True, "lemons") -def test_ratio_divide(): - assert ratio_divide(10, [1]) == [10] - assert ratio_divide(10, [1, 1]) == [5, 5] - assert ratio_divide(12, [1, 3]) == [3, 9] - assert ratio_divide(0, [1, 3]) == [0, 0] - assert ratio_divide(0, [1, 3], [1, 1]) == [1, 1] - assert ratio_divide(10, [1, 0]) == [10, 0] +def test_ratio_distribute(): + assert ratio_distribute(10, [1]) == [10] + assert ratio_distribute(10, [1, 1]) == [5, 5] + assert ratio_distribute(12, [1, 3]) == [3, 9] + assert ratio_distribute(0, [1, 3]) == [0, 0] + assert ratio_distribute(0, [1, 3], [1, 1]) == [1, 1] + assert ratio_distribute(10, [1, 0]) == [10, 0]