home · contact · privacy
Add alert highlighting, allow chained drawing attributes. master
authorChristian Heller <c.heller@plomlompom.de>
Sat, 4 Oct 2025 14:00:59 +0000 (16:00 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Sat, 4 Oct 2025 14:00:59 +0000 (16:00 +0200)
src/ircplom/testing.py
src/ircplom/tui_base.py
src/tests/_timeout_retries.test
src/tests/config.test
src/tests/pingpong.test
src/tests/test.test
src/tests/tui_prompt_basics.test

index baf806093ac065a9c362c7d58ba8e335e19368fd..d4f0a8eef898dcc449d6b41aa98cbd61e0559f4c 100644 (file)
@@ -9,7 +9,8 @@ from ircplom.client import IrcConnection, IrcConnSetup
 from ircplom.client_tui import ClientKnowingTui, ClientTui, LOG_PREFIX_IN
 from ircplom.irc_conn import (IrcConnAbortException, IrcConnTimeoutException,
                               IrcMessage)
-from ircplom.tui_base import TerminalInterface, TuiEvent
+from ircplom.tui_base import (TerminalInterface, TuiEvent,
+                              LOG_FMT_ALERT, LOG_FMT_HIGHLIGHT, LOG_FMT_NONE)
 
 
 PATH_TESTS = Path('tests')
@@ -40,7 +41,7 @@ class TestTerminal(QueueMixin, TerminalInterface):
     def write(self,
               msg: str = '',
               start_y: Optional[int] = None,
-              attribute: Optional[str] = None,
+              attributes: str = '',
               padding: bool = True
               ) -> None:
         pass
@@ -138,12 +139,14 @@ class _Playbook:
 
         def split_server_put_and_log(line: str, **_) -> list[str]:
             context, msg = self._split_by_context_separator(line)
-            assert msg[0] in '.*' and msg[1:3] == f'{LOG_PREFIX_IN} '
+            assert msg[0] in {LOG_FMT_NONE, LOG_FMT_HIGHLIGHT}
+            assert msg[1] in {LOG_FMT_NONE, LOG_FMT_ALERT}
+            assert msg[2:4] == f'{LOG_PREFIX_IN} '
             c_id, win_ids = context[1:].split(_CHAR_ID_TYPE_SEP, maxsplit=1)
-            return [f'{_CHAR_SERVER_MSG}{c_id}{_CHAR_CONTEXT_SEP}{msg[3:]}',
+            return [f'{_CHAR_SERVER_MSG}{c_id}{_CHAR_CONTEXT_SEP}{msg[4:]}',
                     win_ids + _CHAR_CONTEXT_SEP + msg]
 
-        def repeat(line: str, anchors: dict[str, int], **_) -> list[str]:
+        def repeat(line: str, anchors: dict[str, int], **__) -> list[str]:
             range_data = line[len(_TOK_REPEAT) + 1:].split(
                     _CHAR_RANGE_DATA_SEP, maxsplit=2)
             start_key, end_key = range_data[:2]
@@ -155,7 +158,7 @@ class _Playbook:
             for jdx, insert in enumerate(inserts):
                 if (not insert) or insert.startswith(_CHAR_ANCHOR):
                     continue
-                context, msg = self._split_by_context_separator(insert)
+                _, msg = self._split_by_context_separator(insert)
                 inserts[jdx] = _CHAR_CONTEXT_SEP.join([range_data[2]] + [msg])
             return inserts
 
@@ -252,8 +255,8 @@ class TestingClientTui(ClientTui):
 
     def log(self, msg: str, **kwargs) -> tuple[tuple[int, ...], str]:
         win_ids, logged_msg = super().log(msg, **kwargs)
-        time_str, msg_sans_time = logged_msg[1:].split(' ', maxsplit=1)
-        msg_sans_time = logged_msg[0] + msg_sans_time
+        time_str, msg_sans_time = logged_msg[2:].split(' ', maxsplit=1)
+        msg_sans_time = logged_msg[:2] + msg_sans_time
         assert len(time_str) == 8
         for c in time_str[:2] + time_str[3:5] + time_str[6:]:
             assert c.isdigit()
index ce26c955b273b57f5ce744bad7e359022f586085..6c4cc506bff63903db59d4b8c2dffe7dd8be7e55 100644 (file)
@@ -14,7 +14,9 @@ from blessed import Terminal as BlessedTerminal
 from ircplom.events import AffectiveEvent, Loop, QueueMixin, QuitEvent
 
 _LOG_PREFIX_DEFAULT = '#'
-_LOG_PREFIX_ALERT = '!'
+LOG_FMT_NONE = '.'
+LOG_FMT_ALERT = '!'
+LOG_FMT_HIGHLIGHT = '*'
 
 _MIN_HEIGHT = 4
 _MIN_WIDTH = 32
@@ -160,13 +162,15 @@ class _HistoryWidget(_ScrollableWidget):
                    + self._wrapped[bookmark_idx_pos:])
 
         to_write_w_attrs: list[tuple[Optional[str], str]] = []
-        do_highlight = False
+        attrs: str
         prev_idx_unwrapped: Optional[int] = -1
         for idx_unwrapped, line in wrapped[start_idx_neg:end_idx_neg]:
             if idx_unwrapped != prev_idx_unwrapped:
-                do_highlight = line[:1] == '*'
+                attrs = ','.join(
+                        (['bold'] if line[:1] == LOG_FMT_HIGHLIGHT else []) +
+                        (['red'] if line[1:2] == LOG_FMT_ALERT else []))
                 prev_idx_unwrapped = idx_unwrapped
-            to_write_w_attrs += [('bold' if do_highlight else None, line)]
+            to_write_w_attrs += [(attrs, line)]
 
         if add_scroll_info:
             scroll_info = f'vvv [{(-1) * self._wrapped_idx_neg}] '
@@ -174,7 +178,7 @@ class _HistoryWidget(_ScrollableWidget):
             to_write_w_attrs += [('reverse', scroll_info)]
 
         for idx, line_t in enumerate(to_write_w_attrs):
-            self._write(start_y=idx, attribute=line_t[0], msg=line_t[1])
+            self._write(start_y=idx, attributes=line_t[0], msg=line_t[1])
 
         hist_idx_pos = self._wrapped[(end_idx_neg or 0) - 1][0]
         self._last_read_idx_pos = max(self._last_read_idx_pos,
@@ -254,7 +258,7 @@ class PromptWidget(_ScrollableWidget):
                         + _PROMPT_ELL_OUT)
         self._write(to_write[:cursor_x_to_write], self._sizes.y,
                     padding=False)
-        self._write(to_write[cursor_x_to_write], attribute='reverse',
+        self._write(to_write[cursor_x_to_write], attributes='reverse',
                     padding=False)
         self._write(to_write[cursor_x_to_write + 1:])
 
@@ -456,7 +460,7 @@ class TerminalInterface(ABC):
     def write(self,
               msg: str = '',
               start_y: Optional[int] = None,
-              attribute: Optional[str] = None,
+              attributes: str = '',
               padding: bool = True
               ) -> None:
         'Print to terminal, with position, padding to line end, attributes.'
@@ -487,12 +491,12 @@ class BaseTui(QueueMixin):
     def log(self, msg: str, **kwargs) -> tuple[tuple[int, ...], str]:
         'Write with timestamp, prefix to what window ._log_target_wins offers.'
         prefix = kwargs.get('prefix', _LOG_PREFIX_DEFAULT)
-        if kwargs.get('alert', False):
-            prefix = _LOG_PREFIX_ALERT + prefix
         now = str(datetime.now())
         today, time = now[:10], now[11:19]
-        highlight = '*' if kwargs.get('highlight', False) else '.'
-        msg = f'{highlight}{time} {prefix} {msg}'
+        fmt = ''
+        for t in (('highlight', LOG_FMT_HIGHLIGHT), ('alert', LOG_FMT_ALERT)):
+            fmt += t[1] if kwargs.get(t[0], False) else LOG_FMT_NONE
+        msg = f'{fmt}{time} {prefix} {msg}'
         affected_win_indices = []
         for win in self._log_target_wins(**kwargs):
             affected_win_indices += [win.idx]
@@ -715,7 +719,7 @@ class Terminal(QueueMixin, TerminalInterface):
     def write(self,
               msg: str = '',
               start_y: Optional[int] = None,
-              attribute: Optional[str] = None,
+              attributes: str = '',
               padding: bool = True
               ) -> None:
         if start_y is not None:
@@ -729,8 +733,8 @@ class Terminal(QueueMixin, TerminalInterface):
         elif padding:
             msg += ' ' * len_padding
             end_x = self.size.x
-        if attribute:
-            msg = getattr(self._blessed, attribute)(msg)
+        for attr in [attr for attr in attributes.split(',') if attr]:
+            msg = getattr(self._blessed, attr)(msg)
         print(msg, end='')
         self._cursor_yx = _YX(self._cursor_yx.y, end_x)
 
index da91cb63be5d8c135c8af8b5f1f48ed3f3289bb6..c2ceebf184d206f1e63d27ea79d92658069febf3 100644 (file)
@@ -5,80 +5,80 @@
 
 | clientwin-init-in
 | isupport-clear-in
-1 .$ isupport cleared
-1 .$ isupport:CHANTYPES set to: [#&]
-1 .$ isupport:PREFIX set to: [(ov)@+]
-1 .$ isupport:USERLEN set to: [10]
+1 ..$ isupport cleared
+1 ..$ isupport:CHANTYPES set to: [#&]
+1 ..$ isupport:PREFIX set to: [(ov)@+]
+1 ..$ isupport:USERLEN set to: [10]
 | isupport-clear-out
-1 .$ caps cleared
-1 .$ users cleared
-1 .$ channels cleared
+1 ..$ caps cleared
+1 ..$ users cleared
+1 ..$ channels cleared
 | clientwin-init-out
-, .$ DISCONNECTED
-1 .$ hostname set to: [foo.bar.baz]
+, ..$ DISCONNECTED
+1 ..$ hostname set to: [foo.bar.baz]
 | conn-init-retries-in
-1 .$ port set to: [10003]
-1 .$ nick_wanted set to: [foo]
-1 .$ user_wanted set to: [foobarbazquux]
-1 .$ realname set to: [baz]
-1 .$ password set to: [bar]
+1 ..$ port set to: [10003]
+1 ..$ nick_wanted set to: [foo]
+1 ..$ user_wanted set to: [foobarbazquux]
+1 ..$ realname set to: [baz]
+1 ..$ password set to: [bar]
 
-1 .$ connection_state set to: [connecting]
-1 .$ port set to: [10002]
-1 .$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
+1 ..$ connection_state set to: [connecting]
+1 ..$ port set to: [10002]
+1 ..$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
 1 .!$ will retry connecting in 1 seconds
 
-1 .$ connection_state set to: [connecting]
-1 .$ port set to: [10001]
-1 .$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
+1 ..$ connection_state set to: [connecting]
+1 ..$ port set to: [10001]
+1 ..$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
 1 .!$ will retry connecting in 2 seconds
 
-1 .$ connection_state set to: [connecting]
-1 .$ port set to: [10000]
-1 .$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
+1 ..$ connection_state set to: [connecting]
+1 ..$ port set to: [10000]
+1 ..$ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
 1 .!$ will retry connecting in 4 seconds
 | conn-init-retries-out
 
 # with TestingClient finally having reduced port to 10000, connecting works now
 | conn-full-in
 | conn0-in
-1 .$ connection_state set to: [connecting]
-1 .$ connection_state set to: [connected]
+1 ..$ connection_state set to: [connecting]
+1 ..$ connection_state set to: [connected]
 | conn0-out
-, .$ CONNECTED
+, ..$ CONNECTED
 | conn1-in
-1 .> CAP LS :302
-1 .> USER foobarbazquux 0 * :baz
-1 .> NICK :foo
+1 ..> CAP LS :302
+1 ..> USER foobarbazquux 0 * :baz
+1 ..> NICK :foo
 | conn1-out
 | conn-full-out
 
 # test retry chain also started by in-connection timeout
 <0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .> PING :what's up?
+1 ..> PING :what's up?
 <0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .$ connection_state set to: [broken: no timely PONG from server]
+1 ..$ connection_state set to: [broken: no timely PONG from server]
 repeat isupport-clear-in isupport-clear-out
-1 .$ connection_state set to: []
-, .$ DISCONNECTED
+1 ..$ connection_state set to: []
+, ..$ DISCONNECTED
 1 .!$ will retry connecting in 1 seconds
 repeat conn-full-in conn-full-out
 
 # on second server, check timed auto-retries don't activate after manual intervention
 > /connect baz.bar.foo:10003 foo:bar baz:foobarbazquux
 repeat clientwin-init-in clientwin-init-out 2
-, .$ DISCONNECTED
-2 .$ hostname set to: [baz.bar.foo]
+, ..$ DISCONNECTED
+2 ..$ hostname set to: [baz.bar.foo]
 repeat conn-init-retries-in conn-init-retries-out 2
 > /window 2
 > /reconnect
 repeat conn0-in conn0-out 2
-, .$ CONNECTED
+, ..$ CONNECTED
 repeat conn1-in conn1-out 2
 wait 4
 > /disconnect
-2 .> QUIT :ircplom says bye
+2 ..> QUIT :ircplom says bye
 wait 4
 
 > /quit
-0 .<
+0 ..<
index 9e8106aa116236a5f21461fd289c4b497210d354..dd45497fcd71b333e38a4b007d4e8b5a6cf7c6fd 100644 (file)
@@ -1,25 +1,25 @@
-0 .# Found config at tests/config.toml, reading …
-0 .# Connecting: {'hostname': 'irc.test0.net', 'nickname': 'foo', 'password': 'bar', 'username': 'baz', 'realname': 'quux', 'port': 1234, 'channels': ['#test', '##testtest']}
-1 .$ isupport cleared
-1 .$ isupport:CHANTYPES set to: [#&]
-1 .$ isupport:PREFIX set to: [(ov)@+]
-1 .$ isupport:USERLEN set to: [10]
-1 .$ caps cleared
-1 .$ users cleared
-1 .$ channels cleared
-, .$ DISCONNECTED
-1 .$ hostname set to: [irc.test0.net]
-1 .$ port set to: [1234]
-1 .$ nick_wanted set to: [foo]
-1 .$ user_wanted set to: [baz]
-1 *$ realname set to: [quux]
-1 .$ password set to: [bar]
-1 .$ connection_state set to: [connecting]
-1 .$ connection_state set to: [connected]
-, .$ CONNECTED
-1 .> CAP LS :302
-1 *> USER baz 0 * :quux
-1 .> NICK :foo
+0 ..# Found config at tests/config.toml, reading …
+0 ..# Connecting: {'hostname': 'irc.test0.net', 'nickname': 'foo', 'password': 'bar', 'username': 'baz', 'realname': 'quux', 'port': 1234, 'channels': ['#test', '##testtest']}
+1 ..$ isupport cleared
+1 ..$ isupport:CHANTYPES set to: [#&]
+1 ..$ isupport:PREFIX set to: [(ov)@+]
+1 ..$ isupport:USERLEN set to: [10]
+1 ..$ caps cleared
+1 ..$ users cleared
+1 ..$ channels cleared
+, ..$ DISCONNECTED
+1 ..$ hostname set to: [irc.test0.net]
+1 ..$ port set to: [1234]
+1 ..$ nick_wanted set to: [foo]
+1 ..$ user_wanted set to: [baz]
+1 *.$ realname set to: [quux]
+1 ..$ password set to: [bar]
+1 ..$ connection_state set to: [connecting]
+1 ..$ connection_state set to: [connected]
+, ..$ CONNECTED
+1 ..> CAP LS :302
+1 *.> USER baz 0 * :quux
+1 ..> NICK :foo
 
 > /quit
 0 .< 
index 8af157628b0bc10dddc2b38339fa1795a84b4f12..291680f8eccb22df2b15a97376ccdbd390d07867 100644 (file)
@@ -1,53 +1,53 @@
 > /connect foo.bar.baz foo:bar baz:foobarbazquux
 | isupport-clear-in
-1 .$ isupport cleared
-1 .$ isupport:CHANTYPES set to: [#&]
-1 .$ isupport:PREFIX set to: [(ov)@+]
-1 .$ isupport:USERLEN set to: [10]
+1 ..$ isupport cleared
+1 ..$ isupport:CHANTYPES set to: [#&]
+1 ..$ isupport:PREFIX set to: [(ov)@+]
+1 ..$ isupport:USERLEN set to: [10]
 | isupport-clear-out
-1 .$ caps cleared
-1 .$ users cleared
-1 .$ channels cleared
-, .$ DISCONNECTED
-1 .$ hostname set to: [foo.bar.baz]
-1 .$ port set to: [-1]
-1 .$ nick_wanted set to: [foo]
-1 .$ user_wanted set to: [foobarbazquux]
-1 .$ realname set to: [baz]
-1 .$ password set to: [bar]
-1 .$ port set to: [6697]
+1 ..$ caps cleared
+1 ..$ users cleared
+1 ..$ channels cleared
+, ..$ DISCONNECTED
+1 ..$ hostname set to: [foo.bar.baz]
+1 ..$ port set to: [-1]
+1 ..$ nick_wanted set to: [foo]
+1 ..$ user_wanted set to: [foobarbazquux]
+1 ..$ realname set to: [baz]
+1 ..$ password set to: [bar]
+1 ..$ port set to: [6697]
 | conn0-in
-1 .$ connection_state set to: [connecting]
-1 .$ connection_state set to: [connected]
+1 ..$ connection_state set to: [connecting]
+1 ..$ connection_state set to: [connected]
 | conn0-out
-, .$ CONNECTED
+, ..$ CONNECTED
 | conn1-in
-1 .> CAP LS :302
-1 .> USER foobarbazquux 0 * :baz
-1 .> NICK :foo
+1 ..> CAP LS :302
+1 ..> USER foobarbazquux 0 * :baz
+1 ..> NICK :foo
 | conn1-out
 
 # ensure we PONG properly
-:0:1 .< PING :?
-1 .> PONG :?
+:0:1 ..< PING :?
+1 ..> PONG :?
 
 # ping on timeout, go on as normal if PONG received 
 | full-timeout-in
 | trigger-ping-in
 <0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .> PING :what's up?
+1 ..> PING :what's up?
 | trigger-ping-out
-:0:1 .< :*.?.net PONG *.?.net :what's up?
-:0:1 .< :*.?.net NOTICE * :*** Looking up your ident...
-2 .< *** [ server] *** Looking up your ident...
+:0:1 ..< :*.?.net PONG *.?.net :what's up?
+:0:1 ..< :*.?.net NOTICE * :*** Looking up your ident...
+2 ..< *** [ server] *** Looking up your ident...
 
 # another timeout instead of pong? disconnect
 repeat trigger-ping-in trigger-ping-out
 <0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .$ connection_state set to: [broken: no timely PONG from server]
+1 ..$ connection_state set to: [broken: no timely PONG from server]
 repeat isupport-clear-in isupport-clear-out
-1 .$ connection_state set to: []
-2 .$ DISCONNECTED
+1 ..$ connection_state set to: []
+2 ..$ DISCONNECTED
 1 .!$ will retry connecting in 1 seconds
 | full-timeout-out
 
@@ -55,9 +55,9 @@ repeat isupport-clear-in isupport-clear-out
 > /window 1
 > /reconnect
 repeat conn0-in conn0-out
-2 .$ CONNECTED
+2 ..$ CONNECTED
 repeat conn1-in conn1-out
 repeat full-timeout-in full-timeout-out
 
 > /quit
-0 .< 
+0 ..
index 72a007bc9ec1d6b796665ec1ff3bbcb2afdd8017..ab814aa8f3bd6c5f5f7ed9e487a8d7fa4035456f 100644 (file)
 > /connect foo.bar.baz foo:bar baz:foobarbazquux
 | standard-clears-in
 | isupport-clear-in
-1 .$ isupport cleared
-1 .$ isupport:CHANTYPES set to: [#&]
-1 .$ isupport:PREFIX set to: [(ov)@+]
-1 .$ isupport:USERLEN set to: [10]
+1 ..$ isupport cleared
+1 ..$ isupport:CHANTYPES set to: [#&]
+1 ..$ isupport:PREFIX set to: [(ov)@+]
+1 ..$ isupport:USERLEN set to: [10]
 | isupport-clear-out
-1 .$ caps cleared
-1 .$ users cleared
-1 .$ channels cleared
+1 ..$ caps cleared
+1 ..$ users cleared
+1 ..$ channels cleared
 | standard-clears-out
-, .$ DISCONNECTED
+, ..$ DISCONNECTED
 
 # connect with values set by /connect, init CAP negotation
-1 .$ hostname set to: [foo.bar.baz]
-1 .$ port set to: [-1]
-1 .$ nick_wanted set to: [foo]
-1 .$ user_wanted set to: [foobarbazquux]
-1 .$ realname set to: [baz]
-1 .$ password set to: [bar]
-1 .$ port set to: [6697]
+1 ..$ hostname set to: [foo.bar.baz]
+1 ..$ port set to: [-1]
+1 ..$ nick_wanted set to: [foo]
+1 ..$ user_wanted set to: [foobarbazquux]
+1 ..$ realname set to: [baz]
+1 ..$ password set to: [bar]
+1 ..$ port set to: [6697]
 | conn0
-1 .$ connection_state set to: [connecting]
-1 .$ connection_state set to: [connected]
+1 ..$ connection_state set to: [connecting]
+1 ..$ connection_state set to: [connected]
 | conn1
-, .$ CONNECTED
+, ..$ CONNECTED
 | conn2
-1 .> CAP LS :302
-1 .> USER foobarbazquux 0 * :baz
-1 .> NICK :foo
+1 ..> CAP LS :302
+1 ..> USER foobarbazquux 0 * :baz
+1 ..> NICK :foo
 
 # expect some NOTICE and PING to process/reply during initiation
-:0:1 .< :*.?.net NOTICE * :*** Looking up your ident...
-2 .< *** [ server] *** Looking up your ident...
-:0:1 .< :*.?.net NOTICE * :*** Looking up your hostname...
-2 .< *** [ server] *** Looking up your hostname...
-:0:1 .< :*.?.net NOTICE * :*** Found your hostname (foo.bar.baz)
-2 .< *** [ server] *** Found your hostname (foo.bar.baz)
-:0:1 .< PING :?
-1 .> PONG :?
+:0:1 ..< :*.?.net NOTICE * :*** Looking up your ident...
+2 ..< *** [ server] *** Looking up your ident...
+:0:1 ..< :*.?.net NOTICE * :*** Looking up your hostname...
+2 ..< *** [ server] *** Looking up your hostname...
+:0:1 ..< :*.?.net NOTICE * :*** Found your hostname (foo.bar.baz)
+2 ..< *** [ server] *** Found your hostname (foo.bar.baz)
+:0:1 ..< PING :?
+1 ..> PONG :?
 
 # handle 433
-:0:1 .< :*.?.net 433 * foo :Nickname already in use
+:0:1 ..< :*.?.net 433 * foo :Nickname already in use
 1 .!$ nickname already in use, trying increment
-1 .> NICK :foo0
-:0:1 .< :*.?.net 433 * foo0 :Nickname already in use
+1 ..> NICK :foo0
+:0:1 ..< :*.?.net 433 * foo0 :Nickname already in use
 1 .!$ nickname already in use, trying increment
-1 .> NICK :foo1
+1 ..> NICK :foo1
 
 # collect server capabilities
-:0:1 .< :*.?.net CAP * LS : foo bar sasl=PLAIN,EXTERNAL baz cap-notify
-1 .> CAP REQ :sasl
-1 .> CAP :LIST
-:0:1 .< :*.?.net CAP * ACK :sasl
-:0:1 .< :*.?.net CAP * LIST :cap-notify sasl
-1 .$ caps:bar:data set to: []
-1 .$ caps:baz:data set to: []
-1 .$ caps:cap-notify:data set to: []
-1 .$ caps:cap-notify:enabled set to: [True]
-1 .$ caps:foo:data set to: []
-1 .$ caps:sasl:data set to: []
-1 .$ caps:sasl:data set to: [PLAIN,EXTERNAL]
-1 .$ caps:sasl:enabled set to: [True]
+:0:1 ..< :*.?.net CAP * LS : foo bar sasl=PLAIN,EXTERNAL baz cap-notify
+1 ..> CAP REQ :sasl
+1 ..> CAP :LIST
+:0:1 ..< :*.?.net CAP * ACK :sasl
+:0:1 ..< :*.?.net CAP * LIST :cap-notify sasl
+1 ..$ caps:bar:data set to: []
+1 ..$ caps:baz:data set to: []
+1 ..$ caps:cap-notify:data set to: []
+1 ..$ caps:cap-notify:enabled set to: [True]
+1 ..$ caps:foo:data set to: []
+1 ..$ caps:sasl:data set to: []
+1 ..$ caps:sasl:data set to: [PLAIN,EXTERNAL]
+1 ..$ caps:sasl:enabled set to: [True]
 
 # authenticate via SASL, collect items of user identity
-1 .$ sasl_auth_state set to: [attempting]
-1 .> AUTHENTICATE :PLAIN
-:0:1 .< AUTHENTICATE +
-1 .> AUTHENTICATE :Zm9vAGZvbwBiYXI=
-:0:1 .< :foo.bar.baz 900 foo1 foo1!foobarbazq@baz.bar.foo foo :You are now logged in as foo
-1 .$ users:me:nick set to: [?]
-1 .$ users:me:nick set to: [foo1]
-1 .$ users:me:user set to: [foobarbazq]
-1 .$ users:me:host set to: [baz.bar.foo]
-1 .$ sasl_account set to: [foo]
-:0:1 .< :foo.bar.baz 903 foo1 :SASL authentication successful
-1 .$ sasl_auth_state set to: [SASL authentication successful]
+1 ..$ sasl_auth_state set to: [attempting]
+1 ..> AUTHENTICATE :PLAIN
+:0:1 ..< AUTHENTICATE +
+1 ..> AUTHENTICATE :Zm9vAGZvbwBiYXI=
+:0:1 ..< :foo.bar.baz 900 foo1 foo1!foobarbazq@baz.bar.foo foo :You are now logged in as foo
+1 ..$ users:me:nick set to: [?]
+1 ..$ users:me:nick set to: [foo1]
+1 ..$ users:me:user set to: [foobarbazq]
+1 ..$ users:me:host set to: [baz.bar.foo]
+1 ..$ sasl_account set to: [foo]
+:0:1 ..< :foo.bar.baz 903 foo1 :SASL authentication successful
+1 ..$ sasl_auth_state set to: [SASL authentication successful]
 
 # finish CAP negotation, thus login procedure
-1 .> CAP :END
+1 ..> CAP :END
 
 # of all pre-MOTD greeting messages, only process isupports
-:0:1 .< :foo.bar.baz 001 foo1 :Welcome to the foo.bar.baz network
+:0:1 ..< :foo.bar.baz 001 foo1 :Welcome to the foo.bar.baz network
 | conn3
-:0:1 .< :foo.bar.baz 002 foo1 :Your host is foo.bar.baz
-:0:1 .< :foo.bar.baz 003 foo1 :This server was created Jan 1 2020
-:0:1 .< :foo.bar.baz 004 foo1 foo.bar.baz ircserver-1.0 abc def ghi
-:0:1 .< :foo.bar.baz 005 foo1 ABC=DEF GHI=JKL :are supported by this server
-1 .$ isupport:ABC set to: [DEF]
-1 .$ isupport:GHI set to: [JKL]
-:0:1 .< :foo.bar.baz 005 foo1 MNO=PQR STU=VWX Y=Z :are supported by this server
-1 .$ isupport:MNO set to: [PQR]
-1 .$ isupport:STU set to: [VWX]
-1 .$ isupport:Y set to: [Z]
-:0:1 .< :foo.bar.baz 251 foo1 :There are 10 users and 1000 invisible on 5 servers
-:0:1 .< :foo.bar.baz 252 foo1 7 :IRC Operators online
-:0:1 .< :foo.bar.baz 253 foo1 4 :unknown connection(s)
-:0:1 .< :foo.bar.baz 254 foo1 800 :channels formed
-:0:1 .< :foo.bar.baz 255 foo1 :I have 100 clients and 1 serveres
-:0:1 .< :foo.bar.baz 265 foo1 100 150 :Current local users 100, max 150
-:0:1 .< :foo.bar.baz 266 foo1 1010 1050 :Current global users 1010, max 1050
-:0:1 .< :foo.bar.baz 250 foo1 :Highest connection count: 151 (150 clients) (1080 connections received)
+:0:1 ..< :foo.bar.baz 002 foo1 :Your host is foo.bar.baz
+:0:1 ..< :foo.bar.baz 003 foo1 :This server was created Jan 1 2020
+:0:1 ..< :foo.bar.baz 004 foo1 foo.bar.baz ircserver-1.0 abc def ghi
+:0:1 ..< :foo.bar.baz 005 foo1 ABC=DEF GHI=JKL :are supported by this server
+1 ..$ isupport:ABC set to: [DEF]
+1 ..$ isupport:GHI set to: [JKL]
+:0:1 ..< :foo.bar.baz 005 foo1 MNO=PQR STU=VWX Y=Z :are supported by this server
+1 ..$ isupport:MNO set to: [PQR]
+1 ..$ isupport:STU set to: [VWX]
+1 ..$ isupport:Y set to: [Z]
+:0:1 ..< :foo.bar.baz 251 foo1 :There are 10 users and 1000 invisible on 5 servers
+:0:1 ..< :foo.bar.baz 252 foo1 7 :IRC Operators online
+:0:1 ..< :foo.bar.baz 253 foo1 4 :unknown connection(s)
+:0:1 ..< :foo.bar.baz 254 foo1 800 :channels formed
+:0:1 ..< :foo.bar.baz 255 foo1 :I have 100 clients and 1 serveres
+:0:1 ..< :foo.bar.baz 265 foo1 100 150 :Current local users 100, max 150
+:0:1 ..< :foo.bar.baz 266 foo1 1010 1050 :Current global users 1010, max 1050
+:0:1 ..< :foo.bar.baz 250 foo1 :Highest connection count: 151 (150 clients) (1080 connections received)
 
 # collect MOTD into a single output (rather than line-by-line)
-:0:1 .< :foo.bar.baz 375 foo1 :- foo.bar.baz Message of the Day -
-:0:1 .< :foo.bar.baz 372 foo1 :- Howdy! -
-:0:1 .< :foo.bar.baz 372 foo1 :- Welcome! -
-:0:1 .< :foo.bar.baz 372 foo1 :- (to this server) -
-:0:1 .< :foo.bar.baz 376 foo1 :End of /MOTD command
-1 .$ motd set to:
-1 .$   - Howdy! -
-1 .$   - Welcome! -
-1 .$   - (to this server) -
+:0:1 ..< :foo.bar.baz 375 foo1 :- foo.bar.baz Message of the Day -
+:0:1 ..< :foo.bar.baz 372 foo1 :- Howdy! -
+:0:1 ..< :foo.bar.baz 372 foo1 :- Welcome! -
+:0:1 ..< :foo.bar.baz 372 foo1 :- (to this server) -
+:0:1 ..< :foo.bar.baz 376 foo1 :End of /MOTD command
+1 ..$ motd set to:
+1 ..$   - Howdy! -
+1 ..$   - Welcome! -
+1 ..$   - (to this server) -
 
 # collect user mode
-:0:1 .< :foo1 MODE foo1 :+Ziw
-1 .$ users:me:modes set to: [+Ziw]
+:0:1 ..< :foo1 MODE foo1 :+Ziw
+1 ..$ users:me:modes set to: [+Ziw]
 
 # handle bot query NOTICE
-:0:1 .< :SaslServ!SaslServ@services.bar.baz NOTICE foo1 :Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
-3 .< *** [SaslServ] Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
+:0:1 ..< :SaslServ!SaslServ@services.bar.baz NOTICE foo1 :Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
+3 ..< *** [SaslServ] Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
 | conn4
 
 # check difference in available commands when switching to client window
 > /join #test
 0 .!# invalid prompt command: /join unknown
 > /list
-0 .# windows available via /window:
-0 .#   0) :start
-0 .#   1) foo.bar.baz :DEBUG
-0 .#   2) foo.bar.baz  server
-0 .#   3) foo.bar.baz SaslServ
+0 ..# windows available via /window:
+0 ..#   0) :start
+0 ..#   1) foo.bar.baz :DEBUG
+0 ..#   2) foo.bar.baz  server
+0 ..#   3) foo.bar.baz SaslServ
 | conn5
 > /window 1
 > /help
-1 .# commands available in this window:
-1 .#   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]
-1 .#   /disconnect [QUIT_MSG]
-1 .#   /help
-1 .#   /join CHANNEL
-1 .#   /list
-1 .#   /nick NEW_NICK
-1 .#   /privmsg TARGET MSG
-1 .#   /prompt_enter
-1 .#   /quit
-1 .#   /raw VERB [PARAMS_STR]
-1 .#   /reconnect
-1 .#   /window TOWARDS
-1 .#   /window.disconnect [QUIT_MSG]
-1 .#   /window.history.scroll DIRECTION
-1 .#   /window.join CHANNEL
-1 .#   /window.nick NEW_NICK
-1 .#   /window.paste
-1 .#   /window.privmsg TARGET MSG
-1 .#   /window.prompt.backspace
-1 .#   /window.prompt.move_cursor DIRECTION
-1 .#   /window.prompt.scroll DIRECTION
-1 .#   /window.raw VERB [PARAMS_STR]
-1 .#   /window.reconnect
+1 ..# commands available in this window:
+1 ..#   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]
+1 ..#   /disconnect [QUIT_MSG]
+1 ..#   /help
+1 ..#   /join CHANNEL
+1 ..#   /list
+1 ..#   /nick NEW_NICK
+1 ..#   /privmsg TARGET MSG
+1 ..#   /prompt_enter
+1 ..#   /quit
+1 ..#   /raw VERB [PARAMS_STR]
+1 ..#   /reconnect
+1 ..#   /window TOWARDS
+1 ..#   /window.disconnect [QUIT_MSG]
+1 ..#   /window.history.scroll DIRECTION
+1 ..#   /window.join CHANNEL
+1 ..#   /window.nick NEW_NICK
+1 ..#   /window.paste
+1 ..#   /window.privmsg TARGET MSG
+1 ..#   /window.prompt.backspace
+1 ..#   /window.prompt.move_cursor DIRECTION
+1 ..#   /window.prompt.scroll DIRECTION
+1 ..#   /window.raw VERB [PARAMS_STR]
+1 ..#   /window.reconnect
 
 # test lack of implementation
-:0:1 .< foo bar baz
+:0:1 ..< foo bar baz
 1 .!$ No handler implemented for: foo bar baz
 
 # test recoverable 432
 > /nick @foo
-1 .> NICK :@foo
-:0:1 .< :*.?.net 432 foo1 @foo :Erroneous nickname
+1 ..> NICK :@foo
+:0:1 ..< :*.?.net 432 foo1 @foo :Erroneous nickname
 1 .!$ nickname refused for bad format, keeping current one
 
 # join channel, collect topic, residents; update me:user from JOIN message; ensure topic.who not affecting users DB
 > /join #test
-1 .> JOIN :#test
-:0:1 .< :foo1!~foobarbaz@baz.bar.foo JOIN #test
-1 .$ users:me:user set to: [~foobarbaz]
-:0:1 .< :foo.bar.baz 332 foo1 #test :foo bar baz
-1 .$ channels:#test:exits cleared
-:0:1 .< :foo.bar.baz 333 foo1 #test bar!~bar@OLD.bar.bar 1234567890
-1 .$ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
-4 .$ bar!~bar@OLD.bar.bar set topic: foo bar baz
-:0:1 .< :foo.bar.baz 353 foo1 @ #test :foo1 @bar
-1 .$ users:1:nick set to: [?]
-1 .$ users:1:nick set to: [bar]
-:0:1 .< :foo.bar.baz 366 foo1 #test :End of /NAMES list.
-1 .$ channels:#test:user_ids set to:
-1 .$   1
-1 .$   me
-4 .$ residents: bar, foo1
+1 ..> JOIN :#test
+:0:1 ..< :foo1!~foobarbaz@baz.bar.foo JOIN #test
+1 ..$ users:me:user set to: [~foobarbaz]
+:0:1 ..< :foo.bar.baz 332 foo1 #test :foo bar baz
+1 ..$ channels:#test:exits cleared
+:0:1 ..< :foo.bar.baz 333 foo1 #test bar!~bar@OLD.bar.bar 1234567890
+1 ..$ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
+4 ..$ bar!~bar@OLD.bar.bar set topic: foo bar baz
+:0:1 ..< :foo.bar.baz 353 foo1 @ #test :foo1 @bar
+1 ..$ users:1:nick set to: [?]
+1 ..$ users:1:nick set to: [bar]
+:0:1 ..< :foo.bar.baz 366 foo1 #test :End of /NAMES list.
+1 ..$ channels:#test:user_ids set to:
+1 ..$   1
+1 ..$   me
+4 ..$ residents: bar, foo1
 
 # deliver PRIVMSG to channel window, update sender's user+host from metadata
-:0:1 .< :bar!~bar@bar.bar PRIVMSG #test :hi there
-1 .$ users:1:user set to: [~bar]
-1 .$ users:1:host set to: [bar.bar]
-4 .< [bar] hi there
+:0:1 ..< :bar!~bar@bar.bar PRIVMSG #test :hi there
+1 ..$ users:1:user set to: [~bar]
+1 ..$ users:1:host set to: [bar.bar]
+4 ..< [bar] hi there
 
 # check _changing_ TOPIC message is communicated to channel window, as long as either content or who change
-:0:1 .< :bar!~bar@bar.bar TOPIC #test :foo bar baz
-1 .$ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
-4 .$ bar!~bar@bar.bar set topic: foo bar baz
-:0:1 .< :bar!~bar@bar.bar TOPIC #test :foo bar baz
-:0:1 .< :bar!~bar@bar.bar TOPIC #test :abc def ghi
-1 .$ channels:#test:topic set to: [Topic(what='abc def ghi', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
-4 .$ bar!~bar@bar.bar set topic: abc def ghi
+:0:1 ..< :bar!~bar@bar.bar TOPIC #test :foo bar baz
+1 ..$ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
+4 ..$ bar!~bar@bar.bar set topic: foo bar baz
+:0:1 ..< :bar!~bar@bar.bar TOPIC #test :foo bar baz
+:0:1 ..< :bar!~bar@bar.bar TOPIC #test :abc def ghi
+1 ..$ channels:#test:topic set to: [Topic(what='abc def ghi', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
+4 ..$ bar!~bar@bar.bar set topic: abc def ghi
 
 # process non-self channel JOIN
-:0:1 .< :baz!~baz@baz.baz JOIN :#test
-1 .$ users:2:nick set to: [?]
-1 .$ users:2:nick set to: [baz]
-1 .$ users:2:user set to: [~baz]
-1 .$ users:2:host set to: [baz.baz]
-1 .$ channels:#test:user_ids set to:
-1 .$   1
-1 .$   2
-1 .$   me
-4 .$ baz!~baz@baz.baz joins
+:0:1 ..< :baz!~baz@baz.baz JOIN :#test
+1 ..$ users:2:nick set to: [?]
+1 ..$ users:2:nick set to: [baz]
+1 ..$ users:2:user set to: [~baz]
+1 ..$ users:2:host set to: [baz.baz]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   1
+1 ..$   2
+1 ..$   me
+4 ..$ baz!~baz@baz.baz joins
 
 # join second channel with partial residents identity to compare distribution of resident-specific messages
 > /join #testtest
-1 .> JOIN :#testtest
-:0:1 .< :foo1!~foobarbaz@baz.bar.foo JOIN #testtest
-:0:1 .< :foo.bar.baz 332 foo1 #testtest :baz bar foo
-1 .$ channels:#testtest:exits cleared
-:0:1 .< :foo.bar.baz 333 foo1 #testtest bar!~bar@OLD.bar.bar 1234567890
-1 .$ channels:#testtest:topic set to: [Topic(what='baz bar foo', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
-5 .$ bar!~bar@OLD.bar.bar set topic: baz bar foo
-:0:1 .< :foo.bar.baz 353 foo1 @ #testtest :foo1 baz
-:0:1 .< :foo.bar.baz 366 foo1 #testtest :End of /NAMES list.
-1 .$ channels:#testtest:user_ids set to:
-1 .$   2
-1 .$   me
-5 .$ residents: baz, foo1
+1 ..> JOIN :#testtest
+:0:1 ..< :foo1!~foobarbaz@baz.bar.foo JOIN #testtest
+:0:1 ..< :foo.bar.baz 332 foo1 #testtest :baz bar foo
+1 ..$ channels:#testtest:exits cleared
+:0:1 ..< :foo.bar.baz 333 foo1 #testtest bar!~bar@OLD.bar.bar 1234567890
+1 ..$ channels:#testtest:topic set to: [Topic(what='baz bar foo', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
+5 ..$ bar!~bar@OLD.bar.bar set topic: baz bar foo
+:0:1 ..< :foo.bar.baz 353 foo1 @ #testtest :foo1 baz
+:0:1 ..< :foo.bar.baz 366 foo1 #testtest :End of /NAMES list.
+1 ..$ channels:#testtest:user_ids set to:
+1 ..$   2
+1 ..$   me
+5 ..$ residents: baz, foo1
 
 # handle query window with known user
-:0:1 .< :baz!~baz@baz.baz PRIVMSG foo1 :hi there
-6 .< [baz] hi there
+:0:1 ..< :baz!~baz@baz.baz PRIVMSG foo1 :hi there
+6 ..< [baz] hi there
 > /privmsg baz hello, how is it going
-1 .> PRIVMSG baz :hello, how is it going
-6 .> [foo1] hello, how is it going
-:0:1 .< :baz!~baz@baz.baz PRIVMSG foo1 :fine!
-6 .< [baz] fine!
+1 ..> PRIVMSG baz :hello, how is it going
+6 ..> [foo1] hello, how is it going
+:0:1 ..< :baz!~baz@baz.baz PRIVMSG foo1 :fine!
+6 ..< [baz] fine!
 
 # handle failure to query absent user
 > /privmsg barbar hello!
-1 .> PRIVMSG barbar :hello!
-7 .> [foo1] hello!
-:0:1 .< :*.?.net 401 foo1 barbar :No such nick/channel
+1 ..> PRIVMSG barbar :hello!
+7 ..> [foo1] hello!
+:0:1 ..< :*.?.net 401 foo1 barbar :No such nick/channel
 7 .!$ barbar not online
 
 # handle non-self renaming
-:0:1 .< :baz!~baz@baz.baz NICK :bazbaz
-1 .$ users:2:nick set to: [bazbaz]
-4,5,6 .$ baz!~baz@baz.baz renames bazbaz
+:0:1 ..< :baz!~baz@baz.baz NICK :bazbaz
+1 ..$ users:2:nick set to: [bazbaz]
+4,5,6 ..$ baz!~baz@baz.baz renames bazbaz
 
 # handle non-self PART in one of two inhabited channels, preserve identity into re-JOIN
-:0:1 .< :bazbaz!~baz@baz.baz PART :#test
-1 .$ channels:#test:exits:2 set to: [P]
-1 .$ channels:#test:user_ids set to:
-1 .$   1
-1 .$   me
-4 .$ bazbaz!~baz@baz.baz parts
-1 .$ channels:#test:exits:2 cleared
-:0:1 .< :bazbaz!~baz@baz.baz JOIN :#test
-1 .$ channels:#test:user_ids set to:
-1 .$   1
-1 .$   2
-1 .$   me
-4 .$ bazbaz!~baz@baz.baz joins
+:0:1 ..< :bazbaz!~baz@baz.baz PART :#test
+1 ..$ channels:#test:exits:2 set to: [P]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   1
+1 ..$   me
+4 ..$ bazbaz!~baz@baz.baz parts
+1 ..$ channels:#test:exits:2 cleared
+:0:1 ..< :bazbaz!~baz@baz.baz JOIN :#test
+1 ..$ channels:#test:user_ids set to:
+1 ..$   1
+1 ..$   2
+1 ..$   me
+4 ..$ bazbaz!~baz@baz.baz joins
 
 # handle non-self PART in only inhabited channel, lose identity, re-join as new identity
-:0:1 .< :bar!~bar@bar.bar PART :#test
-1 .$ channels:#test:exits:1 set to: [P]
-1 .$ channels:#test:user_ids set to:
-1 .$   2
-1 .$   me
-4 .$ bar!~bar@bar.bar parts
-1 .$ channels:#test:exits:1 cleared
-1 .$ users:1 cleared
-:0:1 .< :bar!~bar@bar.bar JOIN :#test
-1 .$ users:3:nick set to: [?]
-1 .$ users:3:nick set to: [bar]
-1 .$ users:3:user set to: [~bar]
-1 .$ users:3:host set to: [bar.bar]
-1 .$ channels:#test:user_ids set to:
-1 .$   2
-1 .$   3
-1 .$   me
-4 .$ bar!~bar@bar.bar joins
+:0:1 ..< :bar!~bar@bar.bar PART :#test
+1 ..$ channels:#test:exits:1 set to: [P]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   2
+1 ..$   me
+4 ..$ bar!~bar@bar.bar parts
+1 ..$ channels:#test:exits:1 cleared
+1 ..$ users:1 cleared
+:0:1 ..< :bar!~bar@bar.bar JOIN :#test
+1 ..$ users:3:nick set to: [?]
+1 ..$ users:3:nick set to: [bar]
+1 ..$ users:3:user set to: [~bar]
+1 ..$ users:3:host set to: [bar.bar]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   2
+1 ..$   3
+1 ..$   me
+4 ..$ bar!~bar@bar.bar joins
 
 # handle non-self QUIT
-:0:1 .< :bazbaz!~baz@baz.baz QUIT :Client Quit
-1 .$ users:2:exit_msg set to: [QClient Quit]
-6 .$ bazbaz!~baz@baz.baz quits: Client Quit
-1 .$ channels:#test:exits:2 set to: [QClient Quit]
-1 .$ channels:#test:user_ids set to:
-1 .$   3
-1 .$   me
-4 .$ bazbaz!~baz@baz.baz quits: Client Quit
-1 .$ channels:#test:exits:2 cleared
-1 .$ channels:#testtest:exits:2 set to: [QClient Quit]
-1 .$ channels:#testtest:user_ids set to:
-1 .$   me
-5 .$ bazbaz!~baz@baz.baz quits: Client Quit
-1 .$ channels:#testtest:exits:2 cleared
-1 .$ users:2 cleared
+:0:1 ..< :bazbaz!~baz@baz.baz QUIT :Client Quit
+1 ..$ users:2:exit_msg set to: [QClient Quit]
+6 ..$ bazbaz!~baz@baz.baz quits: Client Quit
+1 ..$ channels:#test:exits:2 set to: [QClient Quit]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   3
+1 ..$   me
+4 ..$ bazbaz!~baz@baz.baz quits: Client Quit
+1 ..$ channels:#test:exits:2 cleared
+1 ..$ channels:#testtest:exits:2 set to: [QClient Quit]
+1 ..$ channels:#testtest:user_ids set to:
+1 ..$   me
+5 ..$ bazbaz!~baz@baz.baz quits: Client Quit
+1 ..$ channels:#testtest:exits:2 cleared
+1 ..$ users:2 cleared
 
 # handle self-PART: clear channel, and its squatters
-:0:1 .< :foo1!~foobarbaz@baz.bar.foo PART :#test
-1 .$ channels:#test:exits:me set to: [P]
-1 .$ channels:#test:user_ids set to:
-1 .$   3
-4 .$ foo1!~foobarbaz@baz.bar.foo parts
-1 .$ channels:#test:exits:me cleared
-1 .$ channels:#test cleared
-1 .$ users:3 cleared
+:0:1 ..< :foo1!~foobarbaz@baz.bar.foo PART :#test
+1 ..$ channels:#test:exits:me set to: [P]
+1 ..$ channels:#test:user_ids set to:
+1 ..$   3
+4 ..$ foo1!~foobarbaz@baz.bar.foo parts
+1 ..$ channels:#test:exits:me cleared
+1 ..$ channels:#test cleared
+1 ..$ users:3 cleared
 
 # fail to reconnect while connected
 > /reconnect
 
 # handle /disconnect, clear all
 > /disconnect
-1 .> QUIT :ircplom says bye
-:0:1 .< :foo1!~foobarbaz@baz.bar.foo QUIT :Client Quit
-1 .$ users:me:exit_msg set to: [QClient Quit]
-2,3,6,7 .$ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
-1 .$ channels:#testtest:exits:me set to: [QClient Quit]
-1 .$ channels:#testtest:user_ids set to:
-5 .$ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
-1 .$ channels:#testtest:exits:me cleared
-:0:1 .< ERROR :Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]
-1 .$ connection_state set to: [Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]]
+1 ..> QUIT :ircplom says bye
+:0:1 ..< :foo1!~foobarbaz@baz.bar.foo QUIT :Client Quit
+1 ..$ users:me:exit_msg set to: [QClient Quit]
+2,3,6,7 ..$ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
+1 ..$ channels:#testtest:exits:me set to: [QClient Quit]
+1 ..$ channels:#testtest:user_ids set to:
+5 ..$ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
+1 ..$ channels:#testtest:exits:me cleared
+:0:1 ..< ERROR :Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]
+1 ..$ connection_state set to: [Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]]
 repeat isupport-clear-in isupport-clear-out
-1 .$ caps cleared
-1 .$ channels cleared
-1 .$ connection_state set to: []
-2,3,4,5,6,7 .$ DISCONNECTED
-1 .$ motd set to:
-1 .$ sasl_account set to: []
-1 .$ sasl_auth_state set to: []
+1 ..$ caps cleared
+1 ..$ channels cleared
+1 ..$ connection_state set to: []
+2,3,4,5,6,7 ..$ DISCONNECTED
+1 ..$ motd set to:
+1 ..$ sasl_account set to: []
+1 ..$ sasl_auth_state set to: []
 
 # fail to send in disconnect, check alert window is command prompt window
 > /window 6
 > /privmsg barbar test
-1 .$ users cleared
+1 ..$ users cleared
 6 .!$ cannot send, connection seems closed
 > /window 1
 > /privmsg barbar test
@@ -357,53 +357,53 @@ repeat isupport-clear-in isupport-clear-out
 # test setting up second client, but 432 irrecoverably
 > /connect baz.bar.foo ?foo foo:foo
 repeat standard-clears-in standard-clears-out 8
-, .$ DISCONNECTED
-8 .$ hostname set to: [baz.bar.foo]
-8 .$ port set to: [-1]
-8 .$ nick_wanted set to: [?foo]
-8 .$ user_wanted set to: [foo]
-8 .$ realname set to: [foo]
-8 .$ port set to: [6697]
+, ..$ DISCONNECTED
+8 ..$ hostname set to: [baz.bar.foo]
+8 ..$ port set to: [-1]
+8 ..$ nick_wanted set to: [?foo]
+8 ..$ user_wanted set to: [foo]
+8 ..$ realname set to: [foo]
+8 ..$ port set to: [6697]
 repeat conn0 conn1 8
-, .$ CONNECTED
-1:8 .> CAP LS :302
-1:8 .> USER foo 0 * :foo
-1:8 .> NICK :?foo
-:1:8 .< :*.?.net 432 * ?foo :Erroneous nickname
+, ..$ CONNECTED
+1:8 ..> CAP LS :302
+1:8 ..> USER foo 0 * :foo
+1:8 ..> NICK :?foo
+:1:8 ..< :*.?.net 432 * ?foo :Erroneous nickname
 repeat isupport-clear-in isupport-clear-out 8
-8 .$ connection_state set to: []
-, .$ DISCONNECTED
+8 ..$ connection_state set to: []
+, ..$ DISCONNECTED
 8 .!$ nickname refused for bad format, giving up
 
 # test failing third connection
 > /connect baz.baz.baz baz baz:baz
 repeat standard-clears-in standard-clears-out 9
-, .$ DISCONNECTED
-9 .$ hostname set to: [baz.baz.baz]
-9 .$ port set to: [-1]
-9 .$ nick_wanted set to: [baz]
-9 .$ user_wanted set to: [baz]
-9 .$ realname set to: [baz]
-9 .$ port set to: [6697]
+, ..$ DISCONNECTED
+9 ..$ hostname set to: [baz.baz.baz]
+9 ..$ port set to: [-1]
+9 ..$ nick_wanted set to: [baz]
+9 ..$ user_wanted set to: [baz]
+9 ..$ realname set to: [baz]
+9 ..$ port set to: [6697]
 repeat conn0 conn1 9
-, .$ CONNECTED
-2:9 .> CAP LS :302
-2:9 .> USER baz 0 * :baz
-2:9 .> NICK :baz
+, ..$ CONNECTED
+2:9 ..> CAP LS :302
+2:9 ..> USER baz 0 * :baz
+2:9 ..> NICK :baz
 <2 FAKE_IRC_CONN_ABORT_EXCEPTION
-9 .$ connection_state set to: [broken: FAKE_IRC_CONN_ABORT_EXCEPTION]
+9 ..$ connection_state set to: [broken: FAKE_IRC_CONN_ABORT_EXCEPTION]
 repeat isupport-clear-in isupport-clear-out 9
-9 .$ connection_state set to: []
-, .$ DISCONNECTED
+9 ..$ connection_state set to: []
+, ..$ DISCONNECTED
 
 # check that (save TUI tests assuming start on window 0, and no 4 yet) on reconnect, all the same effects can be expected
 > /reconnect
 repeat conn0 conn1
-2,3,4,5,6,7 .$ CONNECTED
+2,3,4,5,6,7 ..$ CONNECTED
 repeat conn2 conn3
-1 .> JOIN :#testtest
+1 ..> JOIN :#testtest
 repeat conn3 conn4
 repeat conn5 conn6
 
 > /quit
-0 .< 
+0 ..
index 7cb09a697ae660c3f121189d8f4f109885a3cede..6e20fd4808b8fc42d495f11599be18c0543c14c2 100644 (file)
 
 # some simple expected command successes
 > /help
-0 .# commands available in this window:
-0 .#   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]
-0 .#   /help
-0 .#   /list
-0 .#   /prompt_enter
-0 .#   /quit
-0 .#   /window TOWARDS
-0 .#   /window.history.scroll DIRECTION
-0 .#   /window.paste
-0 .#   /window.prompt.backspace
-0 .#   /window.prompt.move_cursor DIRECTION
-0 .#   /window.prompt.scroll DIRECTION
+0 ..# commands available in this window:
+0 ..#   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]
+0 ..#   /help
+0 ..#   /list
+0 ..#   /prompt_enter
+0 ..#   /quit
+0 ..#   /window TOWARDS
+0 ..#   /window.history.scroll DIRECTION
+0 ..#   /window.paste
+0 ..#   /window.prompt.backspace
+0 ..#   /window.prompt.move_cursor DIRECTION
+0 ..#   /window.prompt.scroll DIRECTION
 > /list
-0 .# windows available via /window:
-0 .#   0) :start
+0 ..# windows available via /window:
+0 ..#   0) :start
 
 # should probably not be available at all by explicit prompt writing, but for now this be the expected behavior …
 > /prompt_enter
@@ -41,4 +41,4 @@
 > /window.paste
 
 > /quit
-0 .< 
+0 ..