@@ -210,7 +210,7 @@ def get_optimal_width(self, container_width: int) -> int:
210
210
lines = self .without_spans .split ("\n " )
211
211
return max (line .cell_length for line in lines )
212
212
213
- def wrap (
213
+ def _wrap_and_format (
214
214
self ,
215
215
width : int ,
216
216
align : TextAlign = "left" ,
@@ -219,8 +219,22 @@ def wrap(
219
219
tab_size : int = 8 ,
220
220
selection : Selection | None = None ,
221
221
selection_style : Style | None = None ,
222
- ) -> list [ContentLine ]:
223
- output_lines : list [ContentLine ] = []
222
+ ) -> list [FormattedLine ]:
223
+ """Wraps the text and applies formatting.
224
+
225
+ Args:
226
+ width: Desired width.
227
+ align: Text alignment.
228
+ overflow: Overflow method.
229
+ no_wrap: Disabled wrapping.
230
+ tab_size: Cell with of tabs.
231
+ selection: Selection information or `None` if no selection.
232
+ selection_style: Selection style, or `None` if no selection.
233
+
234
+ Returns:
235
+ List of formatted lines.
236
+ """
237
+ output_lines : list [FormattedLine ] = []
224
238
225
239
if selection is not None :
226
240
get_span = selection .get_span
@@ -236,7 +250,7 @@ def get_span(y: int) -> tuple[int, int] | None:
236
250
end = len (line .plain )
237
251
line = line .stylize (selection_style , start , end )
238
252
239
- content_line = ContentLine (
253
+ content_line = FormattedLine (
240
254
line .expand_tabs (tab_size ), width , y = y , align = align
241
255
)
242
256
@@ -246,7 +260,7 @@ def get_span(y: int) -> tuple[int, int] | None:
246
260
offsets = divide_line (line .plain , width , fold = overflow == "fold" )
247
261
divided_lines = content_line .content .divide (offsets )
248
262
new_lines = [
249
- ContentLine (
263
+ FormattedLine (
250
264
content .rstrip_end (width ), width , offset , y , align = align
251
265
)
252
266
for content , offset in zip (divided_lines , [0 , * offsets ])
@@ -277,7 +291,7 @@ def render_strips(
277
291
selection_style = None
278
292
279
293
align = self ._align
280
- lines = self .wrap (
294
+ lines = self ._wrap_and_format (
281
295
width ,
282
296
align = align ,
283
297
overflow = (
@@ -292,11 +306,11 @@ def render_strips(
292
306
if height is not None :
293
307
lines = lines [:height ]
294
308
295
- strip_lines = [line .to_strip (style ) for line in lines ]
309
+ strip_lines = [line .to_strip (widget , style ) for line in lines ]
296
310
return strip_lines
297
311
298
312
def get_height (self , width : int ) -> int :
299
- lines = self .wrap (width )
313
+ lines = self ._wrap_and_format (width )
300
314
return len (lines )
301
315
302
316
def __len__ (self ) -> int :
@@ -982,7 +996,9 @@ def highlight_regex(
982
996
return Content (self ._text , spans )
983
997
984
998
985
- class ContentLine :
999
+ class FormattedLine :
1000
+ """A line of content with additional formatting information."""
1001
+
986
1002
def __init__ (
987
1003
self ,
988
1004
content : Content ,
@@ -991,13 +1007,15 @@ def __init__(
991
1007
y : int = 0 ,
992
1008
align : TextAlign = "left" ,
993
1009
line_end : bool = False ,
1010
+ link_style : Style | None = None ,
994
1011
) -> None :
995
1012
self .content = content
996
1013
self .width = width
997
1014
self .x = x
998
1015
self .y = y
999
1016
self .align = align
1000
1017
self .line_end = line_end
1018
+ self .link_style = link_style
1001
1019
self .highlight_style : Style | None = None
1002
1020
self .highlight_range : tuple [int | None , int | None ] | None = None
1003
1021
@@ -1009,7 +1027,7 @@ def highlight(self, style: Style, start: int | None, end: int | None) -> None:
1009
1027
self .highlight_style = style
1010
1028
self .highlight_range = (start , end )
1011
1029
1012
- def to_strip (self , style : Style ) -> Strip :
1030
+ def to_strip (self , widget : Widget , style : Style ) -> Strip :
1013
1031
_Segment = Segment
1014
1032
align = self .align
1015
1033
width = self .width
@@ -1024,8 +1042,6 @@ def to_strip(self, style: Style) -> Strip:
1024
1042
1025
1043
if align in ("start" , "left" ) or (align == "justify" and self .line_end ):
1026
1044
pass
1027
- # pad_right = width - self.content.cell_length
1028
- # pad_right = 0
1029
1045
1030
1046
elif align == "center" :
1031
1047
excess_space = width - self .content .cell_length
@@ -1061,7 +1077,7 @@ def to_strip(self, style: Style) -> Strip:
1061
1077
if index < len (spaces ) and (pad := spaces [index ]):
1062
1078
add_segment (_Segment (" " * pad , (style + text_style ).rich_style ))
1063
1079
1064
- strip = Strip (segments , width )
1080
+ strip = Strip (self . _apply_link_style ( widget , segments ) , width )
1065
1081
return strip
1066
1082
1067
1083
segments = (
@@ -1080,9 +1096,32 @@ def to_strip(self, style: Style) -> Strip:
1080
1096
segments .append (
1081
1097
_Segment (" " * pad_right , style .background_style .rich_style )
1082
1098
)
1083
- strip = Strip (segments , content .cell_length + pad_left + pad_right )
1099
+ strip = Strip (
1100
+ self ._apply_link_style (widget , segments ),
1101
+ content .cell_length + pad_left + pad_right ,
1102
+ )
1084
1103
return strip
1085
1104
1105
+ def _apply_link_style (
1106
+ self , widget : Widget , segments : list [Segment ]
1107
+ ) -> list [Segment ]:
1108
+ link_style = widget .link_style
1109
+ _Segment = Segment
1110
+ segments = [
1111
+ _Segment (
1112
+ text ,
1113
+ (
1114
+ style
1115
+ if style ._meta is None
1116
+ else (style + link_style if "@click" in style .meta else style )
1117
+ ),
1118
+ control ,
1119
+ )
1120
+ for text , style , control in segments
1121
+ if style is not None
1122
+ ]
1123
+ return segments
1124
+
1086
1125
1087
1126
if __name__ == "__main__" :
1088
1127
from rich import print
@@ -1116,7 +1155,7 @@ def to_strip(self, style: Style) -> Strip:
1116
1155
"will" , Style (background = Color .parse ("rgba(255, 255, 20, 0.3)" ))
1117
1156
)
1118
1157
1119
- lines = content .wrap (40 , align = "full" )
1158
+ lines = content ._wrap_and_format (40 , align = "full" )
1120
1159
print (lines )
1121
1160
print ("x" * 40 )
1122
1161
for line in lines :
0 commit comments