From 87e8630416bbccf08f454d46922a908ff8f39076 Mon Sep 17 00:00:00 2001 From: arkuhn Date: Wed, 18 Jun 2025 02:00:36 -0400 Subject: [PATCH] fix(syntax): prevent clipping with syntax + padding Reduce render width by padding to keep wrapped lines within console width/prevent clipping. --- CHANGELOG.md | 6 ++++++ CONTRIBUTORS.md | 1 + rich/syntax.py | 11 ++++++++++- tests/test_syntax.py | 25 +++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10933867af..e3bb1cadfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fix: word‐wrapped `Syntax` with padding clipped characters (#3727). + ## [14.0.0] - 2025-03-30 ### Added diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9893915a4a..267bab2b15 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -37,6 +37,7 @@ The following people have contributed to the development of Rich: - [Hugo van Kemenade](https://github.com/hugovk) - [Andrew Kettmann](https://github.com/akettmann) - [Alexander Krasnikov](https://github.com/askras) +- [Adam Kuhn](https://github.com/arkuhn) - [Martin Larralde](https://github.com/althonos) - [Hedy Li](https://github.com/hedythedev) - [Henry Mai](https://github.com/tanducmai) diff --git a/rich/syntax.py b/rich/syntax.py index cff8fd235d..3e8d8058f0 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -625,7 +625,16 @@ def __rich_measure__( def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: - segments = Segments(self._get_syntax(console, options)) + # Reduce available width by padding if necessary, otherwise content is clipped + inner_options = options + if self.padding: + _, pad_right, _, pad_left = Padding.unpack(self.padding) + if pad_left or pad_right: + inner_width = max(0, options.max_width - pad_left - pad_right) + inner_options = options.update_width(inner_width) + + segments = Segments(self._get_syntax(console, inner_options)) + if self.padding: yield Padding(segments, style=self._get_base_style(), pad=self.padding) else: diff --git a/tests/test_syntax.py b/tests/test_syntax.py index bbd4c7a5cb..c1979764fb 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -423,6 +423,31 @@ def test_background_color_override_includes_padding(): ) +def test_syntax_word_wrap_with_horizontal_padding(): + """Regression test for https://github.com/Textualize/rich/issues/3727""" + + EXAMPLE_CODE = """\ + class ListViewExample(App): + def compose(self) -> ComposeResult: + yield ListView( + ListItem(Label("One")), + ListItem(Label("Two")), + ListItem(Label("Three")), + ) + yield Footer()\ + """ + width = 32 + console = Console(width=width, file=io.StringIO(), record=True) + + syntax = Syntax(EXAMPLE_CODE, "python", word_wrap=True, padding=(0, 2)) + console.print(syntax) + text_output = console.export_text() + + assert "One" in text_output + assert "Two" in text_output + assert "Three" in text_output + + if __name__ == "__main__": syntax = Panel.fit( Syntax(