mirror of
https://github.com/Textualize/rich.git
synced 2025-12-23 07:08:35 +00:00
Fixed Text.wrap trimming lines in no_wrap mode
Previously, `rstrip_end` and `truncate` were being called even when soft wrapping was enabled, which led to visual bugs where trailing spaces and their backgrounds were incorrectly trimmed. This change ensures that line trimming logic is now correctly applied only during hard wrapping. This also updates the expected output in a `Syntax` test that was dependent on the old buggy behavior. Fixes #3841
This commit is contained in:
parent
ea9d4db5d8
commit
fb00d7be6c
5 changed files with 26 additions and 5 deletions
|
|
@ -6,6 +6,11 @@ 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).
|
||||
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
- Fixed Text.wrap trimming lines in no_wrap mode https://github.com/Textualize/rich/issues/3841
|
||||
|
||||
## [14.1.0] - 2025-06-25
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ The following people have contributed to the development of Rich:
|
|||
- [Antony Milne](https://github.com/AntonyMilneQB)
|
||||
- [Michael Milton](https://github.com/multimeric)
|
||||
- [Martina Oefelein](https://github.com/oefe)
|
||||
- [Igor Oleynik](https://github.com/KiGamji)
|
||||
- [Nathan Page](https://github.com/nathanrpage97)
|
||||
- [Dave Pearson](https://github.com/davep/)
|
||||
- [Avi Perl](https://github.com/avi-perl)
|
||||
|
|
|
|||
|
|
@ -1236,14 +1236,13 @@ class Text(JupyterMixin):
|
|||
else:
|
||||
offsets = divide_line(str(line), width, fold=wrap_overflow == "fold")
|
||||
new_lines = line.divide(offsets)
|
||||
for line in new_lines:
|
||||
line.rstrip_end(width)
|
||||
for line in new_lines:
|
||||
line.rstrip_end(width)
|
||||
line.truncate(width, overflow=wrap_overflow)
|
||||
if wrap_justify:
|
||||
new_lines.justify(
|
||||
console, width, justify=wrap_justify, overflow=wrap_overflow
|
||||
)
|
||||
for line in new_lines:
|
||||
line.truncate(width, overflow=wrap_overflow)
|
||||
lines.extend(new_lines)
|
||||
return lines
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ def test_python_render_simple_indent_guides() -> None:
|
|||
)
|
||||
rendered_syntax = render(syntax)
|
||||
print(repr(rendered_syntax))
|
||||
expected = '\x1b[34mdef\x1b[0m\x1b[37m \x1b[0m\x1b[32mloop_first_last\x1b[0m(values: Iterable[T]) -> Iterable[Tuple[\x1b[36mb\x1b[0m\n\x1b[2;37m│ \x1b[0m\x1b[33m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[2m│ \x1b[0miter_values = \x1b[36miter\x1b[0m(values)\n\x1b[2m│ \x1b[0m\x1b[34mtry\x1b[0m:\n\x1b[2m│ │ \x1b[0mprevious_value = \x1b[36mnext\x1b[0m(iter_values)\n\x1b[2m│ \x1b[0m\x1b[34mexcept\x1b[0m \x1b[36mStopIteration\x1b[0m:\n\x1b[2m│ │ \x1b[0m\x1b[34mreturn\x1b[0m\n\x1b[2m│ \x1b[0mfirst = \x1b[34mTrue\x1b[0m\n\x1b[2m│ \x1b[0m\x1b[34mfor\x1b[0m value \x1b[35min\x1b[0m iter_values:\n\x1b[2m│ │ \x1b[0m\x1b[34myield\x1b[0m first, \x1b[34mFalse\x1b[0m, previous_value\n\x1b[2m│ │ \x1b[0mfirst = \x1b[34mFalse\x1b[0m\n\x1b[2m│ │ \x1b[0mprevious_value = value\n\x1b[2m│ \x1b[0m\x1b[34myield\x1b[0m first, \x1b[34mTrue\x1b[0m, previous_value\n'
|
||||
expected = '\x1b[34mdef\x1b[0m\x1b[37m \x1b[0m\x1b[32mloop_first_last\x1b[0m(values: Iterable[T]) -> Iterable[Tuple[\x1b[36mbool\x1b[0m, \x1b[36mbool\x1b[0m, T]]:\n\x1b[2;37m│ \x1b[0m\x1b[33m"""Iterate and generate a tuple with a flag for first and last value."""\x1b[0m\n\x1b[2m│ \x1b[0miter_values = \x1b[36miter\x1b[0m(values)\n\x1b[2m│ \x1b[0m\x1b[34mtry\x1b[0m:\n\x1b[2m│ │ \x1b[0mprevious_value = \x1b[36mnext\x1b[0m(iter_values)\n\x1b[2m│ \x1b[0m\x1b[34mexcept\x1b[0m \x1b[36mStopIteration\x1b[0m:\n\x1b[2m│ │ \x1b[0m\x1b[34mreturn\x1b[0m\n\x1b[2m│ \x1b[0mfirst = \x1b[34mTrue\x1b[0m\n\x1b[2m│ \x1b[0m\x1b[34mfor\x1b[0m value \x1b[35min\x1b[0m iter_values:\n\x1b[2m│ │ \x1b[0m\x1b[34myield\x1b[0m first, \x1b[34mFalse\x1b[0m, previous_value\n\x1b[2m│ │ \x1b[0mfirst = \x1b[34mFalse\x1b[0m\n\x1b[2m│ │ \x1b[0mprevious_value = value\n\x1b[2m│ \x1b[0m\x1b[34myield\x1b[0m first, \x1b[34mTrue\x1b[0m, previous_value\n'
|
||||
assert rendered_syntax == expected
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -641,6 +641,22 @@ def test_no_wrap_no_crop():
|
|||
)
|
||||
|
||||
|
||||
def test_no_wrap_no_strip_trailing_space():
|
||||
"""Test that Text.wrap doesn't strip trailing spaces from styled segments in no wrap mode."""
|
||||
console = Console(width=40)
|
||||
|
||||
text = Text()
|
||||
text.append("x" * 35)
|
||||
text.append(" test ", style="white on blue")
|
||||
|
||||
lines = text.wrap(console, width=40, no_wrap=True)
|
||||
|
||||
assert len(lines) == 1
|
||||
result_text = lines[0]
|
||||
|
||||
assert result_text.plain == "x" * 35 + " test "
|
||||
|
||||
|
||||
def test_fit():
|
||||
text = Text("Hello\nWorld")
|
||||
lines = text.fit(3)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue