Skip to content

Commit 0f2f51b

Browse files
authored
Merge pull request #3521 from Textualize/splitcells-fix
Segment.split_cells fix
2 parents 8b84ee9 + 661ae8d commit 0f2f51b

File tree

4 files changed

+41
-26
lines changed

4 files changed

+41
-26
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## Unreleased
8+
## [13.9.2] - 2024-10-04
99

1010
### Fixed
1111

1212
- Fixed `Table` columns not highlighting when added by `add_row` https://github.com/Textualize/rich/issues/3517
13+
- Fixed an issue with Segment.split_cells reported in Textual https://github.com/Textualize/textual/issues/5090
1314

1415
## [13.9.1] - 2024-10-01
1516

@@ -2096,6 +2097,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr
20962097

20972098
- First official release, API still to be stabilized
20982099

2100+
[13.9.2]: https://github.com/textualize/rich/compare/v13.9.1...v13.9.2
20992101
[13.9.1]: https://github.com/textualize/rich/compare/v13.9.0...v13.9.1
21002102
[13.9.0]: https://github.com/textualize/rich/compare/v13.8.1...v13.9.0
21012103
[13.8.1]: https://github.com/textualize/rich/compare/v13.8.0...v13.8.1

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "rich"
33
homepage = "https://github.com/Textualize/rich"
44
documentation = "https://rich.readthedocs.io/en/latest/"
5-
version = "13.9.1"
5+
version = "13.9.2"
66
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
77
authors = ["Will McGugan <willmcgugan@gmail.com>"]
88
license = "MIT"

rich/segment.py

+16-19
Original file line numberDiff line numberDiff line change
@@ -129,34 +129,31 @@ def _split_cells(cls, segment: "Segment", cut: int) -> Tuple["Segment", "Segment
129129

130130
cell_size = get_character_cell_size
131131

132-
pos = int((cut / cell_length) * (len(text))) - 1
133-
if pos < 0:
134-
pos = 0
132+
pos = int((cut / cell_length) * len(text))
135133

136-
before = text[:pos]
137-
cell_pos = cell_len(before)
138-
if cell_pos == cut:
139-
return (
140-
_Segment(before, style, control),
141-
_Segment(text[pos:], style, control),
142-
)
143-
while pos < len(text):
144-
char = text[pos]
145-
pos += 1
146-
cell_pos += cell_size(char)
134+
while True:
147135
before = text[:pos]
148-
if cell_pos == cut:
136+
cell_pos = cell_len(before)
137+
out_by = cell_pos - cut
138+
if not out_by:
149139
return (
150140
_Segment(before, style, control),
151141
_Segment(text[pos:], style, control),
152142
)
153-
if cell_pos > cut:
143+
if out_by == -1 and cell_size(text[pos]) == 2:
154144
return (
155-
_Segment(before[: pos - 1] + " ", style, control),
145+
_Segment(text[:pos] + " ", style, control),
146+
_Segment(" " + text[pos + 1 :], style, control),
147+
)
148+
if out_by == +1 and cell_size(text[pos - 1]) == 2:
149+
return (
150+
_Segment(text[: pos - 1] + " ", style, control),
156151
_Segment(" " + text[pos:], style, control),
157152
)
158-
159-
raise AssertionError("Will never reach here")
153+
if cell_pos < cut:
154+
pos += 1
155+
else:
156+
pos -= 1
160157

161158
def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]:
162159
"""Split segment in to two segments at the specified column.

tests/test_segment.py

+21-5
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,30 @@ def test_split_cells_emoji(text, split, result):
285285
assert Segment(text).split_cells(split) == result
286286

287287

288-
def test_split_cells_mixed() -> None:
288+
@pytest.mark.parametrize(
289+
"segment",
290+
[
291+
Segment("早乙女リリエル (CV: 徳井青)"),
292+
Segment("メイド・イン・きゅんクチュアリ☆ "),
293+
Segment("TVアニメ「メルクストーリア -無気力少年と瓶の中の少女-」 主題歌CD"),
294+
Segment("南無阿弥JKうらめしや?! "),
295+
Segment("メルク (CV: 水瀬いのり) "),
296+
Segment(" メルク (CV: 水瀬いのり) "),
297+
Segment(" メルク (CV: 水瀬いのり) "),
298+
Segment(" メルク (CV: 水瀬いのり) "),
299+
],
300+
)
301+
def test_split_cells_mixed(segment: Segment) -> None:
289302
"""Check that split cells splits on cell positions."""
290303
# Caused https://github.com/Textualize/textual/issues/4996 in Textual
291-
test = Segment("早乙女リリエル (CV: 徳井青)")
292-
for position in range(1, test.cell_length):
293-
left, right = Segment.split_cells(test, position)
304+
305+
for position in range(0, segment.cell_length + 1):
306+
left, right = Segment.split_cells(segment, position)
307+
assert all(
308+
cell_len(c) > 0 for c in segment.text
309+
) # Sanity check there aren't any sneaky control codes
294310
assert cell_len(left.text) == position
295-
assert cell_len(right.text) == test.cell_length - position
311+
assert cell_len(right.text) == segment.cell_length - position
296312

297313

298314
def test_split_cells_doubles() -> None:

0 commit comments

Comments
 (0)