diff --git a/CHANGELOG.md b/CHANGELOG.md index b8b15a173..36ac7188f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Deprecated `PRIORITY_BINDINGS` class variable. - Renamed `char` to `character` on Key event. - Renamed `key_name` to `name` on Key event. -- Moved Ctrl+C, tab, and shift+tab to App BINDINGS - Queries/`walk_children` no longer includes self in results by default https://github.com/Textualize/textual/pull/1416 ## [0.7.0] - 2022-12-17 diff --git a/docs/guide/input.md b/docs/guide/input.md index a966f8c68..cf147cb62 100644 --- a/docs/guide/input.md +++ b/docs/guide/input.md @@ -160,7 +160,7 @@ The tuple of three strings may be enough for simple bindings, but you can also r ### Priority bindings -Textual checks bindings for the focused widget first. If there is no matching binding, then the parent widget(s) will be checked. Occasionally, you may want bindings to be checked *before* the focused widget. Typically to create hot-keys. +Individual bindings may be marked as a *priority*, which means they will be checked prior to the bindings of the focused widget. This feature is often used to create hot-keys on the app or screen. Such bindings can not be disabled by binding the same key on a widget. You can create priority key bindings by setting `priority=True` on the Binding object. Textual uses this feature to add a default binding for ++ctrl+c++ so there is always a way to exit the app. Here's the bindings from the App base class. Note the first binding is set as a priority: diff --git a/src/textual/events.py b/src/textual/events.py index 6f229b358..1f509a072 100644 --- a/src/textual/events.py +++ b/src/textual/events.py @@ -200,10 +200,12 @@ class Key(InputEvent): __slots__ = ["key", "character", "aliases"] - def __init__(self, sender: MessageTarget, key: str, char: str | None) -> None: + def __init__(self, sender: MessageTarget, key: str, character: str | None) -> None: super().__init__(sender) self.key = key - self.character = (key if len(key) == 1 else None) if char is None else char + self.character = ( + (key if len(key) == 1 else None) if character is None else character + ) self.aliases = _get_key_aliases(key) def __rich_repr__(self) -> rich.repr.Result: diff --git a/tests/test_message_pump.py b/tests/test_message_pump.py index 749afa1d8..ce665f7c9 100644 --- a/tests/test_message_pump.py +++ b/tests/test_message_pump.py @@ -17,7 +17,7 @@ class ValidWidget(Widget): async def test_dispatch_key_valid_key(): widget = ValidWidget() - result = await widget.dispatch_key(Key(widget, key="x", char="x")) + result = await widget.dispatch_key(Key(widget, key="x", character="x")) assert result is True assert widget.called_by == widget.key_x @@ -26,7 +26,7 @@ async def test_dispatch_key_valid_key_alias(): """When you press tab or ctrl+i, it comes through as a tab key event, but handlers for tab and ctrl+i are both considered valid.""" widget = ValidWidget() - result = await widget.dispatch_key(Key(widget, key="tab", char="\t")) + result = await widget.dispatch_key(Key(widget, key="tab", character="\t")) assert result is True assert widget.called_by == widget.key_ctrl_i @@ -52,5 +52,5 @@ async def test_dispatch_key_raises_when_conflicting_handler_aliases(): In the terminal, they're the same thing, so we fail fast via exception here.""" widget = DuplicateHandlersWidget() with pytest.raises(DuplicateKeyHandlers): - await widget.dispatch_key(Key(widget, key="tab", char="\t")) + await widget.dispatch_key(Key(widget, key="tab", character="\t")) assert widget.called_by == widget.key_tab