From b7d7677ca6f92ff3831c51ae997fec5bb2eec241 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 25 Jul 2025 08:10:38 +0100 Subject: [PATCH] console options optimization --- src/textual/app.py | 21 ++++++++++++++++++++- src/textual/visual.py | 11 +++++++---- src/textual/widgets/_data_table.py | 6 +++--- src/textual/widgets/_input.py | 5 +++-- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index d1209e17a8..d968f10d16 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -53,7 +53,7 @@ import rich import rich.repr from platformdirs import user_downloads_path -from rich.console import Console, RenderableType +from rich.console import Console, ConsoleDimensions, ConsoleOptions, RenderableType from rich.control import Control from rich.protocol import is_renderable from rich.segment import Segment, Segments @@ -1129,6 +1129,25 @@ def current_mode(self) -> str: """The name of the currently active mode.""" return self._current_mode + @property + def console_options(self) -> ConsoleOptions: + """Get options for the Rich console. + + Returns: + Console options (same object returned from `console.options`). + """ + size = ConsoleDimensions(*self.size) + console = self.console + return ConsoleOptions( + max_height=size.height, + size=size, + legacy_windows=console.legacy_windows, + min_width=1, + max_width=size.width, + encoding=console.encoding, + is_terminal=console.is_terminal, + ) + def exit( self, result: ReturnType | None = None, diff --git a/src/textual/visual.py b/src/textual/visual.py index 96fe11951c..64b51b9963 100644 --- a/src/textual/visual.py +++ b/src/textual/visual.py @@ -293,7 +293,8 @@ def get_optimal_width(self, rules: RulesMap, container_width: int) -> int: return width def get_height(self, rules: RulesMap, width: int) -> int: - console = active_app.get().console + app = active_app.get() + console = app.console renderable = self._renderable if isinstance(renderable, Text): height = len( @@ -305,7 +306,8 @@ def get_height(self, rules: RulesMap, width: int) -> int: ) ) else: - options = console.options.update_width(width).update(highlight=False) + console_options = app.console_options + options = console_options.update_width(width).update(highlight=False) segments = console.render(renderable, options) # Cheaper than counting the lines returned from render_lines! height = sum([text.count("\n") for text, _, _ in segments]) @@ -326,8 +328,9 @@ def render_strips( Returns: An list of Strips. """ - console = active_app.get().console - console_options = console.options.update( + app = active_app.get() + console = app.console + console_options = app.console_options.update( highlight=False, width=width, height=height, diff --git a/src/textual/widgets/_data_table.py b/src/textual/widgets/_data_table.py index 7841e3a769..b78ce528a1 100644 --- a/src/textual/widgets/_data_table.py +++ b/src/textual/widgets/_data_table.py @@ -2121,17 +2121,17 @@ def _render_cell( if is_header_cell: row_height = self.header_height - options = self.app.console.options.update_dimensions(width, row_height) + options = self.app.console_options.update_dimensions(width, row_height) else: # If an auto-height row hasn't had its height calculated, we don't fix # the value for `height` so that we can measure the height of the cell. row = self.rows[row_key] if row.auto_height and row.height == 0: row_height = 0 - options = self.app.console.options.update_width(width) + options = self.app.console_options.update_width(width) else: row_height = row.height - options = self.app.console.options.update_dimensions( + options = self.app.console_options.update_dimensions( width, row_height ) diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index 715ab0f5f0..9dd58b62a8 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -601,6 +601,7 @@ def render_line(self, y: int) -> Strip: return Strip.blank(self.size.width) console = self.app.console + console_options = self.app.console_options max_content_width = self.scrollable_content_region.width if not self.value: @@ -617,7 +618,7 @@ def render_line(self, y: int) -> Strip: strip = Strip( console.render( - placeholder, console.options.update_width(max_content_width + 1) + placeholder, console_options.update_width(max_content_width + 1) ) ) else: @@ -650,7 +651,7 @@ def render_line(self, y: int) -> Strip: result.stylize(cursor_style, cursor, cursor + 1) segments = list( - console.render(result, console.options.update_width(self.content_width)) + console.render(result, console_options.update_width(self.content_width)) ) strip = Strip(segments)