'TUI adaptions to Client.'
# built-ins
from getpass import getuser
-from typing import Any, Optional
+from inspect import signature
+from typing import Callable, Optional
# ourselves
from ircplom.tui_base import (BaseTui, PromptWidget, TuiEvent, Window,
CMD_SHORTCUTS)
self.cmd__privmsg(self.stream, msg)
-class ClientTui(BaseTui):
- 'TUI expanded towards Client features.'
+class _ClientWindowsManager:
+ nick_confirmed: bool = False
+ nickname: str = '?'
+ windows: list[_ClientWindow] = []
- def __init__(self, **kwargs) -> None:
- super().__init__(**kwargs)
- self._clients_data: dict[str, dict[str, Any]] = {}
+ def __init__(self, new_window: Callable) -> None:
+ self._tui_new_window = new_window
+ self.windows += [self._new_window(stream)
+ for stream in (STREAM_SERVER, STREAM_RAW)]
- def _new_client_window(self, client_id: str, stream: str) -> _ClientWindow:
- new_idx = len(self._windows)
+ def _new_window(self, stream: str) -> _ClientWindow:
win_class = (_PrivmsgWindow if stream[0:1] != STREAM_PREFIX_META
else _ClientWindow)
- win = win_class(idx=new_idx, term=self._term, _q_out=self._q_out,
- client_id=client_id, stream=stream)
+ win = self._tui_new_window(win_class, stream=stream)
if isinstance(win, _PrivmsgWindow):
- win.prompt.update_prefix(**{k: self._clients_data[client_id][k]
- for k in _PROMPT_UPDATE_TRIGGER_KEYS})
- self._windows += [win]
- self._switch_window(new_idx)
+ win.prompt.update_prefix(
+ **{k: getattr(self, k) for k in _PROMPT_UPDATE_TRIGGER_KEYS})
+ self.windows += [win]
return win
- @property
- def _all_client_wins(self) -> list[_ClientWindow]:
- return [win for win in self._windows if isinstance(win, _ClientWindow)]
-
- def client_wins(self, client_id: str = '') -> list[_ClientWindow]:
- 'All _ClientWindows matching client_id; if none, create basics.'
- wins = [w for w in self._all_client_wins if client_id == w.client_id]
- if not wins:
- for stream in (STREAM_SERVER, STREAM_RAW):
- wins += [self._new_client_window(client_id, stream)]
- return wins
-
- def client_win(self, client_id: str, stream: str) -> _ClientWindow:
- 'That _ClientWindow matching client_id and stream; if none, create.'
- client_wins = self.client_wins(client_id)
- candidates = [win for win in client_wins if win.stream == stream]
- if candidates:
- return candidates[0]
- win = self._new_client_window(client_id=client_id, stream=stream)
- return win
+ def window(self, stream: str) -> _ClientWindow:
+ 'Return client window of stream.'
+ for win in [w for w in self.windows if w.stream == stream]:
+ return win
+ return self._new_window(stream)
- def log_for_client(self, client_id: str, stream: str, msg: str) -> None:
- 'To stream of client_id, log msg.'
+ def log(self, msg: str, stream: str) -> None:
+ 'Log msg to stram.'
if stream == STREAM_GLOB:
- for win in self.client_wins(client_id):
+ for win in self.windows:
win.log.append(msg)
else:
- self.client_win(client_id, stream).log.append(msg)
- self.redraw_affected()
-
- def update_client_data(self, client_id: str, **kwargs) -> None:
- 'Apply kwargs settings to client data, update representation.'
- if client_id not in self._clients_data:
- self._clients_data[client_id] = {}
- clients_data = self._clients_data[client_id]
+ self.window(stream).log.append(msg)
+
+ def update(self, **kwargs) -> bool:
+ 'Apply settings in kwargs, follow represntation update triggres.'
for k, v in kwargs.items():
- clients_data[k] = v
+ setattr(self, k, v)
if _PROMPT_UPDATE_TRIGGER_KEYS & set(kwargs.keys()):
- for prompt in [w.prompt for w in self.client_wins(client_id)
+ for prompt in [w.prompt for w in self.windows
if isinstance(w.prompt, _PrivmsgPromptWidget)]:
- assert isinstance(prompt, _PrivmsgPromptWidget)
- prompt.update_prefix(**{k: clients_data[k]
+ prompt.update_prefix(**{k: getattr(self, k)
for k in _PROMPT_UPDATE_TRIGGER_KEYS})
+ return True
+ return False
+
+
+class ClientTui(BaseTui):
+ 'TUI expanded towards Client features.'
+
+ def __init__(self, **kwargs) -> None:
+ super().__init__(**kwargs)
+ self._client_mngrs: dict[str, _ClientWindowsManager] = {}
+
+ def _new_window(self, win_class, **kwargs) -> Window:
+ new_idx = len(self._windows)
+ win = win_class(idx=new_idx, term=self._term, _q_out=self._q_out,
+ **kwargs)
+ self._windows += [win]
+ self._switch_window(new_idx)
+ return win
+
+ def for_client_do(self, client_id: str, todo: str, **kwargs) -> None:
+ 'Forward todo to appropriate ClientTuiMgr.'
+ if client_id not in self._client_mngrs:
+ self._client_mngrs[client_id] = _ClientWindowsManager(
+ new_window=lambda cls, **kwargs: self._new_window(
+ cls, client_id=client_id, **kwargs))
+ client_data = self._client_mngrs[client_id]
+ method = getattr(client_data, todo)
+ if method(**kwargs) or signature(method).return_annotation is None:
self.redraw_affected()
def cmd__connect(self,
'Create Client and pass it via NewClientEvent.'
split = host_port.split(':', maxsplit=1)
hostname = split[0]
- if hostname in self._clients_data:
+ if hostname in self._client_mngrs:
return f'already set up connection to {hostname}'
port = -1
if len(split) > 1:
).kw(**kwargs))
def _log(self, msg: str, stream: str = STREAM_SERVER) -> None:
- self._ctput('log_for_client', stream=stream, msg=msg)
+ self._ctput('for_client_do', todo='log', stream=stream, msg=msg)
def update_login(self, nick_confirmed: bool, nickname: str = '') -> None:
super().update_login(nick_confirmed, nickname)
- self._ctput('update_client_data', nick_confirmed=self.nick_confirmed,
+ self._ctput('for_client_do', todo='update',
+ nick_confirmed=self.nick_confirmed,
nickname=self.conn_setup.nickname)