From: Christian Heller Date: Mon, 4 Aug 2025 14:57:15 +0000 (+0200) Subject: More Events refactoring. X-Git-Url: https://plomlompom.com/repos/booking/static/%7B%7Bprefix%7D%7D/%7B%7Bdb.prefix%7D%7D/%7B%7Bpath%7D%7D%7B%7Bblock%5Bdirection%5D.id_%7D%7D?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=ircplom More Events refactoring. --- diff --git a/ircplom/client.py b/ircplom/client.py index c95c99d..81c5384 100644 --- a/ircplom/client.py +++ b/ircplom/client.py @@ -31,15 +31,6 @@ class ClientIdMixin: class ClientEvent(AffectiveEvent, ClientIdMixin): 'To affect Client identified by ClientIdMixin.' - @classmethod - def make_subtype(cls, method_to_call: str, **kwargs - ) -> type['ClientEvent']: - 'Return subclass whose .affect calls method_to_call on target, kwargs.' - class _AdaptedEvent(ClientEvent): - def affect(self, target) -> None: - getattr(target, method_to_call)(**kwargs) - return _AdaptedEvent - class _IrcConnection(BaseIrcConnection): @@ -49,6 +40,7 @@ class _IrcConnection(BaseIrcConnection): super().__init__(**kwargs) def _make_recv_event(self, msg: IrcMessage) -> ClientEvent: + # pylint: disable=unexpected-keyword-arg # confused by client_id= return ClientEvent.make_subtype(method_to_call='handle_msg', msg=msg)( client_id=self.client_id) diff --git a/ircplom/events.py b/ircplom/events.py index 07c82bc..4af5f02 100644 --- a/ircplom/events.py +++ b/ircplom/events.py @@ -22,6 +22,14 @@ class AffectiveEvent(Event, ABC): def affect(self, target: Any) -> None: 'To be run by main loop on target.' + @classmethod + def make_subtype(cls: Any, method_to_call: str, **kwargs): + 'Return subclass whose .affect calls method_to_call on target, kwargs.' + class _AdaptedEvent(cls): + def affect(self, target) -> None: + getattr(target, method_to_call)(**kwargs) + return _AdaptedEvent + @dataclass class PayloadMixin: diff --git a/ircplom/tui_base.py b/ircplom/tui_base.py index cf95132..d3a0379 100644 --- a/ircplom/tui_base.py +++ b/ircplom/tui_base.py @@ -10,9 +10,7 @@ from typing import Callable, Generator, Iterator, NamedTuple, Optional # requirements.txt from blessed import Terminal as BlessedTerminal # ourselves -from ircplom.events import ( - AffectiveEvent, Logger, Loop, PayloadMixin, QueueMixin, QuitEvent) -# from ircplom.irc_conn import IrcMessage +from ircplom.events import AffectiveEvent, Logger, Loop, QueueMixin, QuitEvent _MIN_HEIGHT = 4 _MIN_WIDTH = 32 @@ -349,39 +347,6 @@ class TuiEvent(AffectiveEvent): 'To affect TUI.' -@dataclass -class _KeyboardEvent(TuiEvent, PayloadMixin): - payload: str - - def affect(self, target: 'BaseTui') -> None: - if self.payload[0] == _CHAR_RESIZE: - target.set_screen() - return - if self.payload in _KEYBINDINGS: - cmd_data = _KEYBINDINGS[self.payload] - cmd = target.cmd_name_to_cmd(cmd_data[0]) - if cmd: - cmd(*cmd_data[1:]) - elif self.payload.startswith(_B64_PREFIX): - encoded = self.payload[len(_B64_PREFIX):] - to_paste = '' - for i, c in enumerate(b64decode(encoded).decode('utf-8')): - if i > 512: - break - if c.isprintable(): - to_paste += c - elif c.isspace(): - to_paste += ' ' - else: - to_paste += '#' - target.window.prompt.insert(to_paste) - elif len(self.payload) == 1: - target.window.prompt.insert(self.payload) - else: - target.log.alert(f'unknown keyboard input: {self.payload}') - target.redraw_affected() - - class BaseTui(QueueMixin): 'Base for graphical user interface elements.' @@ -434,6 +399,35 @@ class BaseTui(QueueMixin): self._window_idx = idx self.window.draw() + def handle_keyboard_event(self, typed_in: str) -> None: + 'Translate keyboard input into appropriate actions.' + if typed_in[0] == _CHAR_RESIZE: + self.set_screen() + return + if typed_in in _KEYBINDINGS: + cmd_data = _KEYBINDINGS[typed_in] + cmd = self.cmd_name_to_cmd(cmd_data[0]) + if cmd: + cmd(*cmd_data[1:]) + elif typed_in.startswith(_B64_PREFIX): + encoded = typed_in[len(_B64_PREFIX):] + to_paste = '' + for i, c in enumerate(b64decode(encoded).decode('utf-8')): + if i > 512: + break + if c.isprintable(): + to_paste += c + elif c.isspace(): + to_paste += ' ' + else: + to_paste += '#' + self.window.prompt.insert(to_paste) + elif len(typed_in) == 1: + self.window.prompt.insert(typed_in) + else: + self.log.alert(f'unknown keyboard input: {typed_in}') + self.redraw_affected() + def cmd__prompt_enter(self) -> None: 'Get prompt content from .window.prompt.enter, parse to & run command.' to_parse = self.window.prompt.enter() @@ -559,7 +553,7 @@ class Terminal(QueueMixin): print(msg, end='') self._cursor_yx = _YX(self._cursor_yx.y, end_x) - def _get_keypresses(self) -> Iterator[Optional[_KeyboardEvent]]: + def _get_keypresses(self) -> Iterator[Optional[TuiEvent]]: '''Loop through keypresses from terminal, expand blessed's handling. Explicitly collect KEY_ESCAPE-modified key sequences, and recognize @@ -599,4 +593,6 @@ class Terminal(QueueMixin): to_yield += c else: to_yield = 'esc:' + ':'.join([str(int(b)) for b in chars]) - yield _KeyboardEvent(to_yield) if to_yield else None + yield (TuiEvent.make_subtype('handle_keyboard_event', + typed_in=to_yield)() if to_yield + else None)