Merge pull request #5154 from Textualize/text-area-crop-fix

fix infinite loop in cropping
This commit is contained in:
Will McGugan
2024-10-22 14:13:05 +01:00
committed by GitHub
9 changed files with 971 additions and 622 deletions

View File

@@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
## [0.84.0] - 2024-10-22
### Fixed
- Fixed `RadioSet` not being scrollable https://github.com/Textualize/textual/issues/5100
- Fixed infinite loop in TextArea https://github.com/Textualize/textual/pull/5154
### Added
@@ -2453,6 +2454,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
- New handler system for messages that doesn't require inheritance
- Improved traceback handling
[0.84.0]: https://github.com/Textualize/textual/compare/v0.83.0...v0.84.0
[0.83.0]: https://github.com/Textualize/textual/compare/v0.82.0...v0.83.0
[0.82.0]: https://github.com/Textualize/textual/compare/v0.81.0...v0.82.0
[0.81.0]: https://github.com/Textualize/textual/compare/v0.80.1...v0.81.0

1401
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "textual"
version = "0.83.0"
version = "0.84.0"
homepage = "https://github.com/Textualize/textual"
repository = "https://github.com/Textualize/textual"
documentation = "https://textual.textualize.io/"

View File

@@ -372,10 +372,13 @@ class Strip:
Returns:
A new Strip.
"""
start = max(0, start)
end = self.cell_length if end is None else min(self.cell_length, end)
if start == 0 and end == self.cell_length:
return self
if end <= start:
return Strip([], 0)
cache_key = (start, end)
cached = self._crop_cache.get(cache_key)
if cached is not None:

View File

@@ -1236,9 +1236,7 @@ TextArea {
# Crop the line to show only the visible part (some may be scrolled out of view)
if not self.soft_wrap:
text_strip = text_strip.crop(
scroll_x, scroll_x + virtual_width - gutter_width
)
text_strip = text_strip.crop(scroll_x, scroll_x + virtual_width)
# Stylize the line the cursor is currently on.
if cursor_row == line_index:

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,14 @@
from textual.app import App, ComposeResult
from textual.widgets import TextArea
FAIL_TEXT = "x"
class CodeApp(App):
def compose(self) -> ComposeResult:
yield TextArea(FAIL_TEXT, soft_wrap=False, show_line_numbers=True)
if __name__ == "__main__":
app = CodeApp()
app.run()

View File

@@ -2417,3 +2417,12 @@ def test_pseudo_classes(snap_compare):
self.mount(Label("HELLO"))
assert snap_compare(PSApp())
def test_split_segments_infinite_loop(snap_compare):
"""Regression test for https://github.com/Textualize/textual/issues/5151
Should be a bare-bones text editor containing "x"
"""
assert snap_compare(SNAPSHOT_APPS_DIR / "split_segments.py")

View File

@@ -131,7 +131,7 @@ def test_crop():
assert Strip([Segment("foo")]).crop(1, 3) == Strip([Segment("oo")])
assert Strip([Segment("foo")]).crop(1, 2) == Strip([Segment("o")])
assert Strip([Segment("foo")]).crop(1, 1) == Strip([Segment("")])
assert Strip([Segment("foo")]).crop(1, 1) == Strip([])
assert Strip([Segment("foo💩"), Segment("b💩ar"), Segment("ba💩z")]).crop(
1, 6