@@ -147,101 +147,106 @@ def test_from_ansi_wrapper() -> None:
147147
148148@pytest .mark .parametrize (
149149 # Print with style and verify that everything but newline characters have style.
150- ('objects' , 'expected ' , 'sep ' , 'end ' ),
150+ ('objects' , 'sep ' , 'end ' , 'expected ' ),
151151 [
152152 # Print nothing
153- ((), "\n " , " " , "\n " ),
153+ ((), " " , "\n " , "\n " ),
154154 # Empty string
155- (("" ,), "\n " , " " , "\n " ),
155+ (("" ,), " " , "\n " , "\n " ),
156156 # Multple empty strings
157- (("" , "" ), ' \ x1b [34;47m \x1b [0m\n ' , " " , " \n " ),
157+ (("" , "" ), " " , " \n " , " \ x1b [34;47m \x1b [0m\n " ),
158158 # Basic string
159159 (
160160 ("str_1" ,),
161- "\x1b [34;47mstr_1\x1b [0m\n " ,
162161 " " ,
163162 "\n " ,
163+ "\x1b [34;47mstr_1\x1b [0m\n " ,
164164 ),
165165 # String which ends with newline
166166 (
167167 ("str_1\n " ,),
168- "\x1b [34;47mstr_1\x1b [0m\n \n " ,
169168 " " ,
170169 "\n " ,
170+ "\x1b [34;47mstr_1\x1b [0m\n \n " ,
171171 ),
172172 # String which ends with multiple newlines
173173 (
174174 ("str_1\n \n " ,),
175- "\x1b [34;47mstr_1\x1b [0m\n \n \n " ,
176175 " " ,
177176 "\n " ,
177+ "\x1b [34;47mstr_1\x1b [0m\n \n \n " ,
178178 ),
179179 # Mutiple lines
180180 (
181181 ("str_1\n str_2" ,),
182- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
183182 " " ,
184183 "\n " ,
184+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
185185 ),
186186 # Multiple strings
187187 (
188188 ("str_1" , "str_2" ),
189- "\x1b [34;47mstr_1 str_2\x1b [0m\n " ,
190189 " " ,
191190 "\n " ,
191+ "\x1b [34;47mstr_1 str_2\x1b [0m\n " ,
192192 ),
193193 # Multiple strings with newline between them.
194194 (
195195 ("str_1\n " , "str_2" ),
196- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47m str_2\x1b [0m\n " ,
197196 " " ,
198197 "\n " ,
198+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47m str_2\x1b [0m\n " ,
199199 ),
200200 # Multiple strings and non-space value for sep
201201 (
202202 ("str_1" , "str_2" ),
203- "\x1b [34;47mstr_1(sep)str_2\x1b [0m\n " ,
204203 "(sep)" ,
205204 "\n " ,
205+ "\x1b [34;47mstr_1(sep)str_2\x1b [0m\n " ,
206206 ),
207207 # Multiple strings and sep is a newline
208208 (
209209 ("str_1" , "str_2" ),
210- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
211210 "\n " ,
212211 "\n " ,
212+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
213213 ),
214214 # Multiple strings and sep has newlines
215215 (
216216 ("str_1" , "str_2" ),
217- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\n " ,
218- "(sep1)\n (sep2)" ,
217+ "(sep1)\n (sep2)\n " ,
219218 "\n " ,
219+ ("\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ),
220220 ),
221221 # Non-newline value for end.
222222 (
223223 ("str_1" , "str_2" ),
224- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end)\x1b [0m" ,
225224 "(sep1)\n (sep2)" ,
226225 "(end)" ,
226+ "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end)\x1b [0m" ,
227227 ),
228228 # end has newlines.
229229 (
230230 ("str_1" , "str_2" ),
231- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end1)\x1b [0m\n \x1b [34;47m(end2)\x1b [0m" ,
232- "(sep1)\n (sep2)" ,
233- "(end1)\n (end2)" ,
231+ "(sep1)\n (sep2)\n " ,
232+ "(end1)\n (end2)\n " ,
233+ (
234+ "\x1b [34;47mstr_1(sep1)\x1b [0m\n "
235+ "\x1b [34;47m(sep2)\x1b [0m\n "
236+ "\x1b [34;47mstr_2\x1b [0m\x1b [34;47m(end1)\x1b [0m\n "
237+ "\x1b [34;47m(end2)\x1b [0m\n "
238+ ),
234239 ),
235240 # Empty sep and end values
236241 (
237242 ("str_1" , "str_2" ),
238- "\x1b [34;47mstr_1str_2\x1b [0m" ,
239243 "" ,
240244 "" ,
245+ "\x1b [34;47mstr_1str_2\x1b [0m" ,
241246 ),
242247 ],
243248)
244- def test_apply_style_wrapper (objects : tuple [str ], expected : str , sep : str , end : str ) -> None :
249+ def test_apply_style_wrapper_soft_wrap (objects : tuple [str ], sep : str , end : str , expected : str ) -> None :
245250 # Check if we are still patching Segment.apply_style(). If this check fails, then Rich
246251 # has fixed the bug. Therefore, we can remove this test function and ru._apply_style_wrapper.
247252 assert Segment .apply_style .__func__ is ru ._apply_style_wrapper .__func__ # type: ignore[attr-defined]
@@ -275,3 +280,52 @@ def test_apply_style_wrapper(objects: tuple[str], expected: str, sep: str, end:
275280 finally :
276281 # Restore the patch
277282 Segment .apply_style = ru ._apply_style_wrapper # type: ignore[assignment]
283+
284+
285+ def test_apply_style_wrapper_word_wrap () -> None :
286+ """
287+ Test that our patch didn't mess up word wrapping.
288+ Make sure it does not insert styled newlines or apply style to existing newlines.
289+ """
290+ # Check if we are still patching Segment.apply_style(). If this check fails, then Rich
291+ # has fixed the bug. Therefore, we can remove this test function and ru._apply_style_wrapper.
292+ assert Segment .apply_style .__func__ is ru ._apply_style_wrapper .__func__ # type: ignore[attr-defined]
293+
294+ str1 = "this\n will word wrap\n "
295+ str2 = "and\n so will this\n "
296+ sep = "(sep1)\n (sep2)\n "
297+ end = "(end1)\n (end2)\n "
298+ style = "blue on white"
299+
300+ # All newlines should appear outside of ANSI style sequences.
301+ expected = (
302+ "\x1b [34;47mthis\x1b [0m\n "
303+ "\x1b [34;47mwill word \x1b [0m\n "
304+ "\x1b [34;47mwrap\x1b [0m\n "
305+ "\x1b [34;47m(sep1)\x1b [0m\n "
306+ "\x1b [34;47m(sep2)\x1b [0m\n "
307+ "\x1b [34;47mand\x1b [0m\n "
308+ "\x1b [34;47mso will \x1b [0m\n "
309+ "\x1b [34;47mthis\x1b [0m\n "
310+ "\x1b [34;47m(end1)\x1b [0m\n "
311+ "\x1b [34;47m(end2)\x1b [0m\n "
312+ )
313+
314+ # Set a width which will cause word wrapping.
315+ console = Console (force_terminal = True , width = 10 )
316+
317+ try :
318+ with console .capture () as capture :
319+ console .print (str1 , str2 , sep = sep , end = end , style = style , soft_wrap = False )
320+ assert capture .get () == expected
321+
322+ # Now remove our patch and make sure it produced the same result as unpatched Rich.
323+ Segment .apply_style = ru ._orig_segment_apply_style # type: ignore[assignment]
324+
325+ with console .capture () as capture :
326+ console .print (str1 , str2 , sep = sep , end = end , style = style , soft_wrap = False )
327+ assert capture .get () == expected
328+
329+ finally :
330+ # Restore the patch
331+ Segment .apply_style = ru ._apply_style_wrapper # type: ignore[assignment]
0 commit comments