From 0987229c25fbec2afad6e6c4cb7aed467bb2d99b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 20 Dec 2022 13:19:49 +0000 Subject: [PATCH] fix binding inheritance issues --- src/textual/cli/previews/keys.py | 9 ++++++++- src/textual/dom.py | 2 +- src/textual/widgets/_text_log.py | 23 +++++++++++++++++------ tests/test_binding_inheritance.py | 13 ++++++++++--- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/textual/cli/previews/keys.py b/src/textual/cli/previews/keys.py index 5a0d3f8c7..4facbcb4a 100644 --- a/src/textual/cli/previews/keys.py +++ b/src/textual/cli/previews/keys.py @@ -6,6 +6,13 @@ from textual.containers import Horizontal from textual.widgets import Button, Header, TextLog +INSTRUCTIONS = """\ +Press some keys! + +Because we want to display all the keys, Ctrl+C won't work for this example. Use the button below to quit.\ +""" + + class KeyLog(TextLog, inherit_bindings=False): """We don't want to handle scroll keys.""" @@ -35,7 +42,7 @@ class KeysApp(App, inherit_bindings=False): yield KeyLog() def on_ready(self) -> None: - self.query_one(KeyLog).write(Panel("Press some keys!")) + self.query_one(KeyLog).write(Panel(INSTRUCTIONS), expand=True) def on_key(self, event: events.Key) -> None: self.query_one(KeyLog).write(event) diff --git a/src/textual/dom.py b/src/textual/dom.py index 2ddaf9757..3a4c18435 100644 --- a/src/textual/dom.py +++ b/src/textual/dom.py @@ -22,7 +22,7 @@ from rich.tree import Tree from ._context import NoActiveAppError from ._node_list import NodeList -from .binding import Binding, Bindings, BindingType +from .binding import Bindings, BindingType from .color import BLACK, WHITE, Color from .css._error_tools import friendly_list from .css.constants import VALID_DISPLAY, VALID_VISIBILITY diff --git a/src/textual/widgets/_text_log.py b/src/textual/widgets/_text_log.py index e3405a586..f3338fa8d 100644 --- a/src/textual/widgets/_text_log.py +++ b/src/textual/widgets/_text_log.py @@ -61,11 +61,18 @@ class TextLog(ScrollView, can_focus=True): def _on_styles_updated(self) -> None: self._line_cache.clear() - def write(self, content: RenderableType | object) -> None: + def write( + self, + content: RenderableType | object, + width: int | None = None, + expand: bool = False, + ) -> None: """Write text or a rich renderable. Args: content (RenderableType): Rich renderable (or text). + width (int): Width to render or None to use optimal width. Defaults to None. + expand (bool): Enable expand to widget width, or False to use `width`. """ renderable: RenderableType @@ -88,13 +95,17 @@ class TextLog(ScrollView, can_focus=True): if isinstance(renderable, Text) and not self.wrap: render_options = render_options.update(overflow="ignore", no_wrap=True) - width = max( - self.min_width, - measure_renderables(console, render_options, [renderable]).maximum, - ) + if expand: + render_width = self.scrollable_content_region.width + else: + render_width = ( + measure_renderables(console, render_options, [renderable]).maximum + if width is None + else width + ) segments = self.app.console.render( - renderable, render_options.update_width(width) + renderable, render_options.update_width(render_width) ) lines = list(Segment.split_lines(segments)) if not lines: diff --git a/tests/test_binding_inheritance.py b/tests/test_binding_inheritance.py index 49cc33092..2fa631e5b 100644 --- a/tests/test_binding_inheritance.py +++ b/tests/test_binding_inheritance.py @@ -39,8 +39,10 @@ class NoBindings(App[None]): async def test_just_app_no_bindings() -> None: """An app with no bindings should have no bindings, other than ctrl+c.""" async with NoBindings().run_test() as pilot: - assert list(pilot.app._bindings.keys.keys()) == ["ctrl+c"] + assert list(pilot.app._bindings.keys.keys()) == ["ctrl+c", "tab", "shift+tab"] assert pilot.app._bindings.get_key("ctrl+c").priority is True + assert pilot.app._bindings.get_key("tab").priority is False + assert pilot.app._bindings.get_key("shift+tab").priority is False ############################################################################## @@ -61,7 +63,9 @@ class AlphaBinding(App[None]): async def test_just_app_alpha_binding() -> None: """An app with a single binding should have just the one binding.""" async with AlphaBinding().run_test() as pilot: - assert sorted(pilot.app._bindings.keys.keys()) == sorted(["ctrl+c", "a"]) + assert sorted(pilot.app._bindings.keys.keys()) == sorted( + ["ctrl+c", "tab", "shift+tab", "a"] + ) assert pilot.app._bindings.get_key("ctrl+c").priority is True assert pilot.app._bindings.get_key("a").priority is True @@ -84,7 +88,9 @@ class LowAlphaBinding(App[None]): async def test_just_app_low_priority_alpha_binding() -> None: """An app with a single low-priority binding should have just the one binding.""" async with LowAlphaBinding().run_test() as pilot: - assert sorted(pilot.app._bindings.keys.keys()) == sorted(["ctrl+c", "a"]) + assert sorted(pilot.app._bindings.keys.keys()) == sorted( + ["ctrl+c", "tab", "shift+tab", "a"] + ) assert pilot.app._bindings.get_key("ctrl+c").priority is True assert pilot.app._bindings.get_key("a").priority is False @@ -574,6 +580,7 @@ class PriorityOverlapScreen(Screen): def on_mount(self) -> None: self.query_one(PriorityOverlapWidget).focus() + class PriorityOverlapApp(AppKeyRecorder): """An application with a priority binding."""