From: Christian Heller Date: Sun, 1 Jun 2025 14:46:53 +0000 (+0200) Subject: Refactoring, primarily of interaction between LogBuffer and TuiLoop. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%22https:/validator.w3.org/%7B%7Bprefix%7D%7D/add_structured?a=commitdiff_plain;p=ircplom Refactoring, primarily of interaction between LogBuffer and TuiLoop. --- diff --git a/ircplom.py b/ircplom.py index cb1dfb3..c13de19 100755 --- a/ircplom.py +++ b/ircplom.py @@ -371,16 +371,16 @@ class LogBuffer: _display_size: YX _y_pgscroll: int - def __init__(self, wrap_func: Callable) -> None: - self._wrap = wrap_func + def __init__(self, term: Terminal) -> None: + self._term = term self._history: list[str] = [] self._wrapped: list[tuple[int, str]] = [] self._upscroll_history: int = 0 self._upscroll_wrapped: int = 0 - def apply_geometry(self, display_size: YX) -> None: - 'Calcs .wrapped conditions based on new display_size, stored scroll.' - self._display_size = display_size + def apply_geometry(self, limit_y: int) -> None: + 'Calcs display conditions based on new display_size, stored scroll.' + self._display_size = YX(limit_y, self._term.size.x) self._y_pgscroll = self._display_size.y // 2 self._wrapped.clear() self._wrapped += [(-1, '')] * self._display_size.y @@ -396,7 +396,7 @@ class LogBuffer: self._upscroll_wrapped = len(self._wrapped) - (idx_last + 1) def _add_wrapped(self, idx_original, line) -> int: - wrapped_lines = self._wrap(line) + wrapped_lines = self._term.wrap(line) self._wrapped += [(idx_original, line) for line in wrapped_lines] return len(wrapped_lines) @@ -408,6 +408,21 @@ class LogBuffer: self._upscroll_history += 1 self._upscroll_wrapped += n_wrapped + def draw(self) -> None: + 'Print display_size/scroll-appropriate wrapped selection of lines.' + start_idx = len(self._wrapped) - (self._display_size.y + + self._upscroll_wrapped) + to_write = [t[1] for t in + self._wrapped[start_idx:-(self._upscroll_wrapped + 1)]] + if self._upscroll_wrapped: + scroll_info = f'vvv [{self._upscroll_wrapped}] ' + scroll_info += 'v' * (self._display_size.x - len(scroll_info)) + to_write += [scroll_info] + else: + to_write += [self._wrapped[-1][1]] + for i, line in enumerate(to_write): + self._term.write_yx(YX(i, 0), line) + def scroll(self, up=True) -> None: 'Scrolls view down by half of display size.' self._upscroll_wrapped = ( @@ -419,19 +434,6 @@ class LogBuffer: idx_lowest = self._wrapped[-(self._upscroll_wrapped + 1)][0] self._upscroll_history = len(self._history) - (idx_lowest + 1) - @property - def wrapped(self) -> list[str]: - 'Returns display_size/scroll-appropriately wrapped selection of lines.' - start_idx = len(self._wrapped) - (self._display_size.y - + self._upscroll_wrapped) - to_return = [t[1] for t in - self._wrapped[start_idx:-(self._upscroll_wrapped + 1)]] - if self._upscroll_wrapped: - scroll_info = f'vvv [{self._upscroll_wrapped}] ' - scroll_info += 'v' * (self._display_size.x - len(scroll_info)) - return to_return + [scroll_info] - return to_return + [self._wrapped[-1][1]] - class TuiPrompt: 'Keyboard-controlled command input field.' @@ -475,7 +477,7 @@ class TuiLoop(Loop): def __init__(self, term: Terminal, *args, **kwargs) -> None: self._term = term self._prompt = TuiPrompt(self._term) - self._logs = [LogBuffer(self._term.wrap) for i in range(2)] + self._logs = [LogBuffer(self._term) for i in range(2)] self._log_selected = 0 self._upscroll = 0 self._calc_and_draw_all() @@ -491,7 +493,7 @@ class TuiLoop(Loop): self._logs[1].append(f'<- {event.payload.raw}') elif event.type_ == 'SEND': self._logs[1].append(f'-> {event.payload.raw}') - self._draw_log() + self._log.draw() elif event.type_ == 'KEYBINDING': getattr(self, f'_cmd__{event.payload[0]}')(*event.payload[1:]) elif event.type_ == 'INPUT_CHAR': @@ -503,7 +505,7 @@ class TuiLoop(Loop): # self._log+= [ # f'DEBUG {line}' for line # in '\n'.join(format_exception(event.payload)).split('\n')] - # self._draw_log() + # self._log.draw() else: return True self._term.flush() @@ -513,6 +515,18 @@ class TuiLoop(Loop): def _log(self) -> LogBuffer: return self._logs[self._log_selected] + def _calc_and_draw_all(self) -> None: + self._term.clear() + self._term.calc_geometry() + self._prompt.start_y = self._term.size.y - 1 + self._y_separator = self._term.size.y - 2 + for log in self._logs: + log.apply_geometry(limit_y=self._y_separator) + self._term.write_yx(YX(self._y_separator, 0), '=' * self._term.size.x) + self._term.write_yx(YX(self._prompt.start_y, 0), INPUT_PROMPT) + self._log.draw() + self._prompt.draw() + def _cmd__prompt_backspace(self) -> None: self._prompt.backspace() @@ -550,7 +564,7 @@ class TuiLoop(Loop): def _cmd__scroll(self, direction: str) -> None: self._log.scroll(up=direction == 'up') - self._draw_log() + self._log.draw() def _cmd__disconnect(self, quit_msg: str = 'ircplom says bye') -> None: self.broadcast('SEND', IrcMessage('QUIT', [quit_msg])) @@ -565,28 +579,9 @@ class TuiLoop(Loop): if buffer_idx < 0 or buffer_idx > len(self._logs): return f'unavailable buffer idx: {buffer_idx}' self._log_selected = buffer_idx - self._draw_log() + self._log.draw() return None - def _calc_and_draw_all(self) -> None: - self._term.clear() - self._term.calc_geometry() - self._prompt.start_y = self._term.size.y - 1 - self._y_separator = self._term.size.y - 2 - for log in self._logs: - log.apply_geometry(YX(self._y_separator, self._term.size.x)) - self._draw_frame() - self._draw_log() - self._prompt.draw() - - def _draw_frame(self) -> None: - self._term.write_yx(YX(self._y_separator, 0), '=' * self._term.size.x) - self._term.write_yx(YX(self._prompt.start_y, 0), INPUT_PROMPT) - - def _draw_log(self) -> None: - for i, line in enumerate(self._log.wrapped): - self._term.write_yx(YX(i, 0), line) - class SocketRecvLoop(Loop): 'Loop receiving and translating socket messages towards main loop.'