Skip to content

Commit ccfcc7f

Browse files
authored
Merge pull request #6138 from Textualize/long-placeholder
long placeholder
2 parents 2d98a45 + e81138c commit ccfcc7f

File tree

6 files changed

+236
-17
lines changed

6 files changed

+236
-17
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ 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` https://github.com/Textualize/textual/pull/6138
2728

2829
### Fixed
2930

3031
- Fixed issue where Segments with a style of `None` aren't rendered https://github.com/Textualize/textual/pull/6109
3132
- Fixed visual glitches and crash when changing `DataTable.header_height` https://github.com/Textualize/textual/pull/6128
33+
- Fixed TextArea.placeholder not handling multi-lines https://github.com/Textualize/textual/pull/6138
3234

3335
## [6.1.0] - 2025-08-01
3436

src/textual/content.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,26 @@ 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+
Note that Textual will automatically wrap Content in widgets.
878+
This method is only required if you need some additional processing to lines.
879+
880+
Args:
881+
width: Maximum width of the line (in cells).
882+
align: Alignment of lines.
883+
overflow: Overflow of lines (what happens when the text doesn't fit).
884+
885+
Returns:
886+
A list of Content objects, one per line.
887+
"""
888+
lines = self._wrap_and_format(width, align, overflow)
889+
content_lines = [line.content for line in lines]
890+
return content_lines
891+
872892
def get_style_at_offset(self, offset: int) -> Style:
873893
"""Get the style of a character at give offset.
874894

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

0 commit comments

Comments
 (0)