From aec897a0aedd3572edb00293348d40c01885e01f Mon Sep 17 00:00:00 2001 From: Kevin Turcios Date: Mon, 29 Jun 2026 03:58:13 -0500 Subject: [PATCH 1/3] Optimize syntax word wrap without line numbers --- rich/syntax.py | 13 +++++++++++++ tests/test_syntax.py | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/rich/syntax.py b/rich/syntax.py index 8c8f8315e7..e06b3f1b53 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -743,6 +743,19 @@ def _get_syntax( highlight_number_style, ) = self._get_number_styles(console) + if self.word_wrap and not self.line_numbers: + text = Text("\n").join(lines) + syntax_lines = console.render_lines( + text, + render_options.update(height=None, justify="left"), + style=background_style, + pad=not transparent_background, + new_lines=True, + ) + for syntax_line in syntax_lines: + yield from syntax_line + return + for line_no, line in enumerate(lines, self.start_line + line_offset): if self.word_wrap: wrapped_lines = console.render_lines( diff --git a/tests/test_syntax.py b/tests/test_syntax.py index f27227ea6a..857510124c 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -435,6 +435,29 @@ def test_padding_plus_wrap() -> None: assert output == expected +def test_word_wrap_without_line_numbers_with_line_range() -> None: + console = Console( + width=14, file=io.StringIO(), legacy_windows=False, record=True + ) + syntax = Syntax( + "first line should not appear\n" + "second line wraps around here\n" + "third line stays\n" + "fourth line should not appear", + lexer="text", + word_wrap=True, + line_numbers=False, + line_range=(2, 3), + ) + + console.print(syntax) + + assert ( + console.export_text() + == "second line \nwraps around \nhere \nthird line \nstays \n" + ) + + if __name__ == "__main__": syntax = Panel.fit( Syntax( From c651c4fb6a91ec4f5e061eb5c1094b8350a1e98d Mon Sep 17 00:00:00 2001 From: Kevin Turcios Date: Mon, 29 Jun 2026 04:32:50 -0500 Subject: [PATCH 2/3] Format syntax word wrap test --- tests/test_syntax.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 857510124c..2f2d4bdb3d 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -436,9 +436,7 @@ def test_padding_plus_wrap() -> None: def test_word_wrap_without_line_numbers_with_line_range() -> None: - console = Console( - width=14, file=io.StringIO(), legacy_windows=False, record=True - ) + console = Console(width=14, file=io.StringIO(), legacy_windows=False, record=True) syntax = Syntax( "first line should not appear\n" "second line wraps around here\n" From dd6e32ea15b8de36a34c5633dcab42b8e4f1655c Mon Sep 17 00:00:00 2001 From: Kevin Turcios Date: Mon, 29 Jun 2026 10:56:36 -0500 Subject: [PATCH 3/3] perf(syntax): speed up line-numbered word wrap --- benchmarks/benchmarks.py | 16 ++++++++++++++++ rich/syntax.py | 26 ++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py index 032eecf791..854ebb7359 100644 --- a/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -94,6 +94,22 @@ def _print_with_width(self, width): self.console.print(self.syntax, width) +class SyntaxLineNumbersWrappingSuite: + def setup(self): + self.console = Console( + file=StringIO(), color_system="truecolor", legacy_windows=False + ) + self.syntax = Syntax( + code=snippets.PYTHON_SNIPPET * 120, + lexer="python", + word_wrap=True, + line_numbers=True, + ) + + def time_text_thin_terminal_heavy_wrapping(self): + self.console.print(self.syntax, width=30) + + class TableSuite: def time_table_no_wrapping(self): self._print_table(width=100) diff --git a/rich/syntax.py b/rich/syntax.py index e06b3f1b53..8c656f7609 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -758,12 +758,26 @@ def _get_syntax( for line_no, line in enumerate(lines, self.start_line + line_offset): if self.word_wrap: - wrapped_lines = console.render_lines( - line, - render_options.update(height=None, justify="left"), - style=background_style, - pad=not transparent_background, - ) + wrapped_lines = [ + _Segment.adjust_line_length( + list( + _Segment.apply_style( + wrapped_line.render(console), background_style + ) + ), + render_options.max_width, + style=background_style, + pad=not transparent_background, + ) + for wrapped_line in line.wrap( + console, + render_options.max_width, + justify="left", + overflow=render_options.overflow, + tab_size=self.tab_size, + no_wrap=render_options.no_wrap, + ) + ] else: segments = list(line.render(console, end="")) if options.no_wrap: