Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimized divide #2385

Merged
merged 4 commits into from Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -5,7 +5,7 @@ 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).

## [12.4.5] - Unreleased
## [12.5.0] - 2022-07-11

### Added

Expand All @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Default width of Jupyter console size is increased to 115
- Optimized Segment.divide

### Fixed

Expand All @@ -26,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix edges used in first row of tables when `show_header=False` https://github.com/Textualize/rich/pull/2330
- Fix interaction between `Capture` contexts and `Console(record=True)` https://github.com/Textualize/rich/pull/2343
- Fixed hash issue in Styles class https://github.com/Textualize/rich/pull/2346
- Fixed bug in `Segment.split_and_crop_lines`

### Changed

Expand Down
1 change: 1 addition & 0 deletions asvhashfile
Expand Up @@ -17,6 +17,7 @@ v12.4.1
v12.4.2
v12.4.3
v12.4.4
v12.5.0
v8.0.0
v9.13.0
v9.5.1
30 changes: 22 additions & 8 deletions benchmarks/benchmarks.py
Expand Up @@ -4,6 +4,7 @@
from rich.color import Color, ColorSystem
from rich.console import Console
from rich.pretty import Pretty
from rich.segment import Segment
from rich.style import Style
from rich.syntax import Syntax
from rich.table import Table
Expand All @@ -16,9 +17,10 @@ def setup(self):
file=StringIO(), color_system="truecolor", legacy_windows=False
)
self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)
self.text = Text.from_markup(snippets.MARKUP)

def time_wrapping(self):
Text(snippets.LOREM_IPSUM).wrap(self.console, 12, overflow="fold")
self.text.wrap(self.console, 12, overflow="fold")

def time_indent_guides(self):
Text(snippets.PYTHON_SNIPPET).with_indent_guides()
Expand All @@ -27,7 +29,7 @@ def time_fit(self):
Text(snippets.LOREM_IPSUM).fit(12)

def time_split(self):
Text(snippets.LOREM_IPSUM).split()
self.text.split()

def time_divide(self):
Text(snippets.LOREM_IPSUM).divide(range(20, 100, 4))
Expand All @@ -36,7 +38,7 @@ def time_align_center(self):
Text(snippets.LOREM_IPSUM).align("center", width=self.len_lorem_ipsum * 3)

def time_render(self):
Text(snippets.LOREM_IPSUM).render(self.console)
list(self.text.render(self.console))

def time_wrapping_unicode_heavy(self):
Text(snippets.UNICODE_HEAVY_TEXT).wrap(self.console, 12, overflow="fold")
Expand All @@ -48,15 +50,15 @@ def time_split_unicode_heavy(self):
Text(snippets.UNICODE_HEAVY_TEXT).split()

def time_divide_unicode_heavy(self):
Text(snippets.UNICODE_HEAVY_TEXT).divide(range(20, 100, 4))
self.text.divide(range(20, 100, 4))

def time_align_center_unicode_heavy(self):
Text(snippets.UNICODE_HEAVY_TEXT).align(
"center", width=self.len_lorem_ipsum * 3
)

def time_render_unicode_heavy(self):
Text(snippets.UNICODE_HEAVY_TEXT).render(self.console)
list(Text(snippets.UNICODE_HEAVY_TEXT).render(self.console))


class TextHotCacheSuite:
Expand Down Expand Up @@ -148,6 +150,8 @@ def setup(self):
self.console = Console(
file=StringIO(), color_system="truecolor", legacy_windows=False, width=100
)
self.style1 = Style.parse("blue on red")
self.style2 = Style.parse("green italic bold")

def time_parse_ansi(self):
Style.parse("red on blue")
Expand All @@ -158,6 +162,9 @@ def time_parse_hex(self):
def time_parse_mixed_complex_style(self):
Style.parse("dim bold reverse #00ee00 on rgb(123,12,50)")

def time_style_add(self):
self.style1 + self.style2


class ColorSuite:
def setup(self):
Expand Down Expand Up @@ -199,6 +206,13 @@ def time_downgrade_to_windows(self):

class SegmentSuite:
def setup(self):
self.console = Console(
file=StringIO(), color_system="truecolor", legacy_windows=False, width=100
)
self.line = [
Segment("foo"),
Segment("bar"),
Segment("egg"),
Segment("Where there is a Will"),
Segment("There is a way"),
] * 2

def test_divide_complex(self):
list(Segment.divide(self.line, [5, 10, 20, 50, 108, 110, 118]))
80 changes: 48 additions & 32 deletions benchmarks/results/benchmarks.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions benchmarks/snippets.py
Expand Up @@ -171,3 +171,9 @@ def layout_resolve(total: int, edges: Sequence[EdgeProtocol]) -> List[int]:

出力結果に色やスタイルを追加する方法はいくつかあります。キーワード引数に `style` を追加することで、出力結果全体のスタイルを設定することができます。以下に例を示します:
"""


MARKUP = "\n".join(
"""[bold]Hello [i]World[/i] [bold magenta]foo [i]bar[/i] baz[/] [blue u]https://textualize.io[/]"""
for _ in range(20)
)
2 changes: 1 addition & 1 deletion pyproject.toml
Expand Up @@ -2,7 +2,7 @@
name = "rich"
homepage = "https://github.com/willmcgugan/rich"
documentation = "https://rich.readthedocs.io/en/latest/"
version = "12.4.4"
version = "12.5.0"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
authors = ["Will McGugan <willmcgugan@gmail.com>"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions rich/console.py
Expand Up @@ -1349,6 +1349,7 @@ def render_lines(
render_options.max_width,
include_new_lines=new_lines,
pad=pad,
style=style,
),
None,
render_height,
Expand Down
67 changes: 37 additions & 30 deletions rich/segment.py
Expand Up @@ -18,6 +18,7 @@

from .cells import (
_is_single_cell_widths,
cached_cell_len,
cell_len,
get_character_cell_size,
set_cell_size,
Expand Down Expand Up @@ -290,11 +291,11 @@ def split_and_crop_lines(

for segment in segments:
if "\n" in segment.text and not segment.control:
text, style, _ = segment
text, segment_style, _ = segment
while text:
_text, new_line, text = text.partition("\n")
if _text:
append(cls(_text, style))
append(cls(_text, segment_style))
if new_line:
cropped_line = adjust_line_length(
line, length, style=style, pad=pad
Expand Down Expand Up @@ -602,50 +603,56 @@ def divide(
iter_cuts = iter(cuts)

while True:
try:
cut = next(iter_cuts)
except StopIteration:
cut = next(iter_cuts, -1)
if cut == -1:
return []
if cut != 0:
break
yield []
pos = 0

_cell_len = cell_len
segments_clear = split_segments.clear
segments_copy = split_segments.copy

_cell_len = cached_cell_len
for segment in segments:
text, _style, control = segment
while text:
if control:
end_pos = pos
else:
end_pos = pos + _cell_len(text)
end_pos = pos if control else pos + _cell_len(text)
if end_pos < cut:
add_segment(segment)
pos = end_pos
break

try:
if end_pos == cut:
add_segment(segment)
yield split_segments[:]
del split_segments[:]
pos = end_pos
break
else:
before, segment = segment.split_cells(cut - pos)
text, _style, control = segment
add_segment(before)
yield split_segments[:]
del split_segments[:]
pos = cut
finally:
try:
cut = next(iter_cuts)
except StopIteration:
if end_pos == cut:
add_segment(segment)
yield segments_copy()
segments_clear()
pos = end_pos

cut = next(iter_cuts, -1)
if cut == -1:
if split_segments:
yield split_segments[:]
yield segments_copy()
return
yield split_segments[:]

break

else:
before, segment = segment.split_cells(cut - pos)
text, _style, control = segment
add_segment(before)
yield segments_copy()
segments_clear()
pos = cut

cut = next(iter_cuts, -1)
if cut == -1:
if split_segments:
yield segments_copy()
return

yield segments_copy()


class Segments:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_panel.py
Expand Up @@ -73,7 +73,8 @@ def test_render_size():
Segment(" ", Style()),
Segment("foo"),
Segment(
" "
" ",
Style(),
),
Segment(" ", Style()),
Segment("│", Style()),
Expand Down