From: Christian Heller Date: Tue, 3 Jun 2025 15:52:41 +0000 (+0200) Subject: Some more class abstraction. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%22https:/validator.w3.org/static/%7B%7Bprefix%7D%7D/ledger2?a=commitdiff_plain;p=ircplom Some more class abstraction. --- diff --git a/ircplom.py b/ircplom.py index 241eab1..0751ca2 100755 --- a/ircplom.py +++ b/ircplom.py @@ -371,7 +371,19 @@ class Loop: self._q_to_main.eput('EXCEPTION', e) -class ScrollableWidget(ABC): +class Widget(ABC): + 'Defines most basic TUI object API.' + + @abstractmethod + def set_geometry(self, measurements: tuple[int | YX, ...]) -> None: + 'Update widget\'s measurements, re-generate content where necessary.' + + @abstractmethod + def draw(self) -> None: + 'Print widget\'s content in shape appropriate to set geometry.' + + +class ScrollableWidget(Widget): 'Defines some API shared between PromptWidget and LogWidget.' _history_idx: int @@ -379,18 +391,10 @@ class ScrollableWidget(ABC): self._write_yx = write_yx self._history: list[str] = [] - @abstractmethod - def set_geometry(self, measurements: Any) -> None: - 'Update widget\'s measurements, re-generate content where necessary.' - @abstractmethod def append(self, to_append: str) -> None: 'Append to widget content.' - @abstractmethod - def draw(self) -> None: - 'Print widget\'s content in shape appropriate to applied geometry.' - @abstractmethod def _scroll(self, up=True) -> None: pass @@ -410,8 +414,9 @@ class PromptWidget(ScrollableWidget): self._input_buffer = '' self._history_idx = 0 - def set_geometry(self, measurements: int) -> None: - self._start_y = measurements + def set_geometry(self, measurements: tuple[int | YX, ...]) -> None: + assert isinstance(measurements[0], int) + self._start_y = measurements[0] def append(self, to_append: str) -> None: self._input_buffer += to_append @@ -477,8 +482,9 @@ class LogWidget(ScrollableWidget): self._wrapped += [(idx_original, line) for line in wrapped_lines] return len(wrapped_lines) - def set_geometry(self, measurements: YX) -> None: - self._view_size = measurements + def set_geometry(self, measurements: tuple[int | YX, ...]) -> None: + assert isinstance(measurements[0], YX) + self._view_size = measurements[0] self._y_pgscroll = self._view_size.y // 2 self._wrapped.clear() self._wrapped += [(None, '')] * self._view_size.y @@ -524,7 +530,7 @@ class LogWidget(ScrollableWidget): self._history_idx = history_idx_to_wrapped_idx - len(self._history) -class Window: +class Window(Widget): 'Collects a log and a prompt meant for the same content stream.' def __init__(self, term: Terminal) -> None: @@ -532,13 +538,16 @@ class Window: self.log = LogWidget(self._term.wrap, self._term.write_yx) self.prompt = PromptWidget(self._term.write_yx) - def set_geometry(self, log_height: int, start_y_prompt: int) -> None: - 'Reconfigure included widgets\' geometry.' - self.log.set_geometry(YX(log_height, self._term.size.x)) - self.prompt.set_geometry(start_y_prompt) + def set_geometry(self, measurements: tuple[int | YX, ...]) -> None: + assert len(measurements) == 2 + assert isinstance(measurements[0], int) + assert isinstance(measurements[1], int) + log_height = measurements[0] + start_y_prompt = measurements[1] + self.log.set_geometry((YX(log_height, self._term.size.x),)) + self.prompt.set_geometry((start_y_prompt,)) def draw(self) -> None: - 'Draw both log and prompt.' self.log.draw() self.prompt.draw() @@ -593,7 +602,7 @@ class TuiLoop(Loop): self._term.write_yx(YX(y_separator, 0), '=' * self._term.size.x) self._term.write_yx(YX(y_prompt, 0), INPUT_PROMPT) for window in self._windows: - window.set_geometry(y_separator, y_prompt) + window.set_geometry((y_separator, y_prompt)) self._window.draw() def _cmd__prompt_backspace(self) -> None: