This commit is contained in:
Will McGugan 2020-06-06 13:11:29 +01:00
parent 47bb80ff67
commit 8ad293cf5f
9 changed files with 84 additions and 21 deletions

View File

@ -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/), 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). 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 ## [1.3.1] - 2020-06-01
### Changed ### Changed

View File

@ -10,7 +10,7 @@
Rich is a Python library for _rich_ text and beautiful formatting in the terminal. 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) ![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png)

View File

@ -116,6 +116,48 @@ This produces the following output:
Rich Rich
</span></pre> </span></pre>
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
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #00ff00">──── </span>fold<span style="color: #00ff00"> ────</span>
<span style="color: #000080; font-weight: bold">supercalifragi
listicexpialid
ocious
</span>
<span style="color: #00ff00">──── </span>crop<span style="color: #00ff00"> ────</span>
<span style="color: #000080; font-weight: bold">supercalifragi
</span>
<span style="color: #00ff00">── </span>ellipsis<span style="color: #00ff00"> ──</span>
<span style="color: #000080; font-weight: bold">supercalifrag…
</span>
</pre>
Input Input
----- -----

View File

@ -1,11 +1,11 @@
from typing import List from typing import List
from rich.console import Console, OverflowMethod from rich.console import Console, OverflowMethod
from rich.text import Text
console = Console() console = Console(width=14)
supercali = "supercalifragilisticexpialidocious" supercali = "supercalifragilisticexpialidocious"
overflow_methods: List[OverflowMethod] = ["fold", "crop", "ellipsis"] overflow_methods: List[OverflowMethod] = ["fold", "crop", "ellipsis"]
for overflow in overflow_methods: for overflow in overflow_methods:
console.rule(overflow) console.rule(overflow)
console.print(supercali, overflow=overflow, width=10) console.print(supercali, overflow=overflow, style="bold blue")
console.print()

View File

@ -3,7 +3,6 @@ from math import ceil
from typing import List from typing import List
def ratio_reduce( def ratio_reduce(
total: int, ratios: List[int], maximums: List[int], values: List[int] total: int, ratios: List[int], maximums: List[int], values: List[int]
) -> List[int]: ) -> List[int]:
@ -34,10 +33,10 @@ def ratio_reduce(
return result return result
def ratio_divide( def ratio_distribute(
total: int, ratios: List[int], minimums: List[int] = None total: int, ratios: List[int], minimums: List[int] = None
) -> List[int]: ) -> List[int]:
"""Divide an integer total in to parts based on ratios. """Distribute an integer total in to parts based on ratios.
Args: Args:
total (int): The total to divide. total (int): The total to divide.

View File

@ -690,8 +690,6 @@ class Console:
highlighter=_highlighter, highlighter=_highlighter,
) )
) )
# elif isinstance(renderable, Text):
# append_text(renderable)
elif isinstance(renderable, ConsoleRenderable): elif isinstance(renderable, ConsoleRenderable):
check_text() check_text()
append(renderable) append(renderable)
@ -739,6 +737,7 @@ class Console:
style: Union[str, Style] = None, style: Union[str, Style] = None,
justify: JustifyMethod = None, justify: JustifyMethod = None,
overflow: OverflowMethod = None, overflow: OverflowMethod = None,
no_wrap: bool = None,
emoji: bool = None, emoji: bool = None,
markup: bool = None, markup: bool = None,
highlight: 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. 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``. justify (str, optional): Overflowmethod: "left", "right", "center", or "full". Defaults to ``None``.
overflow (str, optional): Overflow method: "crop", "fold", or "ellipisis". 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``. 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``. 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``. highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``.
@ -773,7 +773,7 @@ class Console:
highlight=highlight, highlight=highlight,
) )
render_options = self.options.update( 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 extend = self._buffer.extend
render = self.render render = self.render

View File

@ -16,7 +16,7 @@ from typing_extensions import Literal
from . import box, errors from . import box, errors
from ._loop import loop_first, loop_first_last, loop_last 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 .jupyter import JupyterMixin
from .measure import Measurement from .measure import Measurement
from .padding import Padding, PaddingDimensions from .padding import Padding, PaddingDimensions
@ -396,7 +396,7 @@ class Table(JupyterMixin):
if column.flexible if column.flexible
] ]
flexible_width = max_width - sum(fixed_widths) 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) iter_flex_widths = iter(flex_widths)
for index, column in enumerate(columns): for index, column in enumerate(columns):
if column.flexible: if column.flexible:
@ -433,7 +433,7 @@ class Table(JupyterMixin):
table_width = sum(widths) table_width = sum(widths)
elif table_width < max_width and self.expand: 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)] widths = [_width + pad for _width, pad in zip(widths, pad_widths)]
return widths return widths

View File

@ -244,3 +244,10 @@ def test_save_html():
console.save_html(export_path) console.save_html(export_path)
with open(export_path, "rt") as html_file: with open(export_path, "rt") as html_file:
assert html_file.read() == expected 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"

View File

@ -1,5 +1,5 @@
from rich._loop import loop_first, loop_last, loop_first_last 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(): def test_loop_first():
@ -29,10 +29,10 @@ def test_loop_first_last():
assert next(iterable) == (False, True, "lemons") assert next(iterable) == (False, True, "lemons")
def test_ratio_divide(): def test_ratio_distribute():
assert ratio_divide(10, [1]) == [10] assert ratio_distribute(10, [1]) == [10]
assert ratio_divide(10, [1, 1]) == [5, 5] assert ratio_distribute(10, [1, 1]) == [5, 5]
assert ratio_divide(12, [1, 3]) == [3, 9] assert ratio_distribute(12, [1, 3]) == [3, 9]
assert ratio_divide(0, [1, 3]) == [0, 0] assert ratio_distribute(0, [1, 3]) == [0, 0]
assert ratio_divide(0, [1, 3], [1, 1]) == [1, 1] assert ratio_distribute(0, [1, 3], [1, 1]) == [1, 1]
assert ratio_divide(10, [1, 0]) == [10, 0] assert ratio_distribute(10, [1, 0]) == [10, 0]