Skip to content

Commit 02fd245

Browse files
committed
long placeholder
1 parent 2d98a45 commit 02fd245

File tree

5 files changed

+75
-17
lines changed

5 files changed

+75
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2424
- Added `Screen.size` https://github.com/Textualize/textual/pull/6105
2525
- Added `compact` to Binding.Group https://github.com/Textualize/textual/pull/6132
2626
- Added `Screen.get_hover_widgets_at` https://github.com/Textualize/textual/pull/6132
27+
- Added `Content.wrap`
2728

2829
### Fixed
2930

src/textual/content.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,23 @@ def iter_content() -> Iterable[Content]:
869869

870870
return Content("".join(text), spans, total_cell_length)
871871

872+
def wrap(
873+
self, width: int, align: TextAlign = "left", overflow: TextOverflow = "fold"
874+
) -> list[Content]:
875+
"""Wrap text so that it fits within the given dimensions.
876+
877+
Args:
878+
width: Maximum width of the line (in cells).
879+
align: Alignment of lines.
880+
overflow: Overflow of lines (what happens when the text doesn't fit).
881+
882+
Returns:
883+
A list of Content objects, one per line.
884+
"""
885+
lines = self._wrap_and_format(width, align, overflow)
886+
content_lines = [line.content for line in lines]
887+
return content_lines
888+
872889
def get_style_at_offset(self, offset: int) -> Style:
873890
"""Get the style of a character at give offset.
874891

src/textual/widgets/_text_area.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,24 +1206,24 @@ def render_line(self, y: int) -> Strip:
12061206
Returns:
12071207
A rendered line.
12081208
"""
1209-
if y == 0 and not self.text and self.placeholder:
1210-
style = self.get_visual_style("text-area--placeholder")
1211-
content = (
1212-
Content(self.placeholder)
1213-
if isinstance(self.placeholder, str)
1214-
else self.placeholder
1215-
)
1216-
content = content.stylize(style)
1217-
if self._draw_cursor:
1218-
theme = self._theme
1219-
cursor_style = theme.cursor_style if theme else None
1220-
if cursor_style:
1221-
content = content.stylize(
1222-
ContentStyle.from_rich_style(cursor_style), 0, 1
1223-
)
1224-
return Strip(
1225-
content.render_segments(self.visual_style), content.cell_length
1209+
1210+
if not self.text and self.placeholder:
1211+
placeholder_lines = Content.from_text(self.placeholder).wrap(
1212+
self.content_size.width
12261213
)
1214+
if y < len(placeholder_lines):
1215+
style = self.get_visual_style("text-area--placeholder")
1216+
content = placeholder_lines[y].stylize(style)
1217+
if self._draw_cursor and y == 0:
1218+
theme = self._theme
1219+
cursor_style = theme.cursor_style if theme else None
1220+
if cursor_style:
1221+
content = content.stylize(
1222+
ContentStyle.from_rich_style(cursor_style), 0, 1
1223+
)
1224+
return Strip(
1225+
content.render_segments(self.visual_style), content.cell_length
1226+
)
12271227

12281228
scroll_x, scroll_y = self.scroll_offset
12291229
absolute_y = scroll_y + y

tests/snapshot_tests/test_snapshots.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4626,3 +4626,27 @@ def compose(self) -> ComposeResult:
46264626
yield Header()
46274627

46284628
assert snap_compare(HeaderApp())
4629+
4630+
4631+
def test_long_textarea_placeholder(snap_compare) -> None:
4632+
4633+
TEXT = """I must not fear.
4634+
Fear is the mind-killer.
4635+
Fear is the little-death that brings total obliteration.
4636+
I will face my fear.
4637+
I will permit it to pass over me and through me.
4638+
And when it has gone past, I will turn the inner eye to see its path.
4639+
Where the fear has gone there will be nothing. Only I will remain."""
4640+
4641+
class PlaceholderApp(App):
4642+
4643+
CSS = """
4644+
TextArea {
4645+
width: 50%;
4646+
}
4647+
"""
4648+
4649+
def compose(self) -> ComposeResult:
4650+
yield TextArea(placeholder=TEXT)
4651+
4652+
assert snap_compare(PlaceholderApp())

tests/test_content.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,19 @@ def test_add_spans() -> None:
349349
Span(7, 9, style="blue"),
350350
]
351351
assert content.spans == expected
352+
353+
354+
def test_wrap() -> None:
355+
content = Content.from_markup("[green]Hello, [b]World, One two three[/b]")
356+
wrapped = content.wrap(6)
357+
print(wrapped)
358+
expected = [
359+
Content("Hello,", spans=[Span(0, 6, style="green")]),
360+
Content("World,", spans=[Span(0, 6, style="green"), Span(0, 6, style="b")]),
361+
Content("One", spans=[Span(0, 3, style="green"), Span(0, 3, style="b")]),
362+
Content("two", spans=[Span(0, 3, style="green"), Span(0, 3, style="b")]),
363+
Content("three", spans=[Span(0, 5, style="green"), Span(0, 5, style="b")]),
364+
]
365+
assert len(wrapped) == len(expected)
366+
for line1, line2 in zip(wrapped, expected):
367+
assert line1.is_same(line2)

0 commit comments

Comments
 (0)