from typing import Callable, Generator, Iterator, Optional
from ircplom.events import Event, Loop, QueueMixin
from ircplom.client import IrcConnection, IrcConnSetup
-from ircplom.client_tui import ClientKnowingTui, ClientTui, LOG_PREFIX_IN
+from ircplom.client_tui import ClientKnowingTui, ClientTui
from ircplom.irc_conn import ERR_STR_TIMEOUT, IrcConnException, IrcMessage
-from ircplom.tui_base import (FormattingString, TerminalInterface, TuiEvent,
- LOG_FMT_SEP, LOG_FMT_ATTRS)
+from ircplom.tui_base import FormattingString, TerminalInterface, TuiEvent
PATH_TESTS = Path('tests')
_MARK_FRAGMENT = '×'
_MARK_INSERT = 'insert'
_MARK_LOG = 'log'
-_MARK_LOGSRVRMSG = 'loggedservermsg'
_MARK_PROMPT = '>'
_MARK_SCREENLINE = 'line'
_MARK_SERVERMSG = 'servermsg'
_SEP_0 = ' '
_SEP_1 = ','
_SEP_2 = ':'
-_TOK_IDX_LOGSRVRMSG = 's'
_TOK_IDX_REPEAT = 'r'
_SIGNATURE_FOR_CMD = {
_MARK_INSERT: (5, 2),
_MARK_LOG: (2, 0),
- _MARK_LOGSRVRMSG: (3, 0),
_MARK_PROMPT: (1, None),
_MARK_SCREENLINE: (3, 0),
_MARK_SERVERMSG: (2, 0),
self._get_client = get_client
self._verbose = verbose
self._print_on_fail: list[str] = []
- self._idx = 0
-
- def expand_parsed(marker: str, parse_into: Callable, **kwargs) -> None:
- new_lines_t: list[tuple[str, str]] = []
- for line_t in reversed(self._lines_t):
- cmd_name, remains = line_t[1].split(_SEP_0, maxsplit=1)
- new_lines_t[0:0] = (
- [line_t] if cmd_name != marker
- else parse_into(line_t[0],
- self._args_for_cmd(cmd_name, remains),
- **kwargs))
- self._lines_t = new_lines_t
- def split_server_put_and_log(index_str: str,
- args: tuple[str, ...],
- **_
- ) -> list[tuple[str, str]]:
- fmt, msg_no_fmt = args[2].split(LOG_FMT_SEP, maxsplit=1)
- for c in fmt[:-1]:
- assert c in LOG_FMT_ATTRS
- assert fmt[0] == LOG_PREFIX_IN
- return [(_SEP_2.join((index_str, _TOK_IDX_LOGSRVRMSG, str(0))),
- _SEP_0.join((_MARK_SERVERMSG, args[0], msg_no_fmt))),
- (_SEP_2.join((index_str, _TOK_IDX_LOGSRVRMSG, str(1))),
- _SEP_0.join((_MARK_LOG, args[1], args[2])))]
+ self._idx = 0
+ with path.open('r', encoding='utf8') as f:
+ self._lines_t = [(str(idx + 1), line.rstrip('\n'))
+ for idx, line in enumerate(f.readlines())
+ if line.rstrip()
+ and not line.startswith(_MARK_COMMENT)]
def insert(index_str: str,
insert_args: tuple[str, ...],
fragments: dict[str, tuple[tuple[str, str], ...]],
- **__
) -> list[tuple[str, str]]:
def crop_to_range(range_str: str) -> None:
bump_int_fields(int(insert_args[2]))
return [(c[0], c[1]) for c in candidates]
- def expand_inserts() -> None:
- fragments: dict[str, tuple[tuple[str, str], ...]] = {}
- anchor = ''
- fragment: list[tuple[str, str]] = []
- fragments_cutoff = 0
- for idx, line_t in enumerate(self._lines_t[:] + [('', '')]):
- if line_t[1].startswith(_MARK_FRAGMENT):
- if anchor:
- fragments[anchor] = tuple(fragment)
- if not line_t[1][len(_MARK_FRAGMENT):].rstrip():
- fragments_cutoff = idx + 1
- break
- anchor = line_t[1].split(_SEP_0, maxsplit=1)[1]
- fragment.clear()
- continue
- fragment += [line_t]
- self._lines_t = self._lines_t[fragments_cutoff:]
- while True:
- snapshot_before = self._lines_t[:]
- expand_parsed(_MARK_INSERT, insert, fragments=fragments)
- if self._lines_t == snapshot_before:
+ fragments: dict[str, tuple[tuple[str, str], ...]] = {}
+ anchor = ''
+ fragment: list[tuple[str, str]] = []
+ fragments_cutoff = 0
+ for idx, line_t in enumerate(self._lines_t[:] + [('', '')]):
+ if line_t[1].startswith(_MARK_FRAGMENT):
+ if anchor:
+ fragments[anchor] = tuple(fragment)
+ if not line_t[1][len(_MARK_FRAGMENT):].rstrip():
+ fragments_cutoff = idx + 1
break
+ anchor = line_t[1].split(_SEP_0, maxsplit=1)[1]
+ fragment.clear()
+ continue
+ fragment += [line_t]
+ self._lines_t = self._lines_t[fragments_cutoff:]
- with path.open('r', encoding='utf8') as f:
- self._lines_t = [(str(idx + 1), line.rstrip('\n'))
- for idx, line in enumerate(f.readlines())
- if line.rstrip()
- and not line.startswith(_MARK_COMMENT)]
- expand_inserts()
- expand_parsed(_MARK_LOGSRVRMSG, split_server_put_and_log)
+ while True:
+ snapshot_before = self._lines_t[:]
+ new_lines_t: list[tuple[str, str]] = []
+ for line_t in reversed(self._lines_t):
+ cmd_name, remains = line_t[1].split(_SEP_0, maxsplit=1)
+ new_lines_t[0:0] = (
+ [line_t] if cmd_name != _MARK_INSERT
+ else insert(line_t[0],
+ self._args_for_cmd(cmd_name, remains),
+ fragments))
+ self._lines_t = new_lines_t
+ if self._lines_t == snapshot_before:
+ break
@staticmethod
def _args_verbose(args: tuple[str, ...]) -> str:
log 1 $ connection_state set to: []
log 2 $ DISCONNECTED
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
×
# to prepare, initiate connection
# handle /disconnect on being connected
> /disconnect
log 1 > QUIT :ircplom says bye
-loggedservermsg 0 1 < ERROR :Closing link: (whatever@whatever.com) [Quit: ircplom says bye]
+insert servermsglogged : +0 MSG ERROR :Closing link: (whatever@whatever.com) [Quit: ircplom says bye]
log 1 $ connection_state set to: [Closing link: (whatever@whatever.com) [Quit: ircplom says bye]]
insert disconnecting
insert connecting
# allow /disconnect outside connection for auto-connect stops
-loggedservermsg 0 1 < ERROR :Closing link: (Connection timed out)
+insert servermsglogged : +0 MSG ERROR :Closing link: (Connection timed out)
log 1 $ connection_state set to: [Closing link: (Connection timed out)]
insert disconnecting
log 1 $ will retry connecting in 1 seconds
insert disconnecting
log 1 $ will retry connecting in 1 seconds
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
× reconnect-error-logged
insert reconnect
-loggedservermsg 0 1 < ERROR :XXX
+insert servermsglogged : +0 MSG ERROR :XXX
log 1 $ connection_state set to: [XXX]
×
insert connecting
# test default ERROR handling
-loggedservermsg 0 1 < ERROR :abc def ghi
+insert servermsglogged : +0 MSG ERROR :abc def ghi
log 1 $ connection_state set to: [abc def ghi]
insert disconnecting
log 1 > USER foobarbazquux 0 * :baz
log 1 > NICK :foo
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
× full-timeout
# ping on timeout, go on as normal if PONG received
insert trigger-ping
-loggedservermsg 0 1 < :*.?.net PONG *.?.net :what's up?
-loggedservermsg 0 1 < :*.?.net NOTICE * :*** Looking up your ident...
+insert servermsglogged : +0 MSG :*.?.net PONG *.?.net :what's up?
+insert servermsglogged : +0 MSG :*.?.net NOTICE * :*** Looking up your ident...
log 2 < (server) *** Looking up your ident...
# another timeout instead of pong? disconnect
insert trigger-ping
insert conn
# ensure we PONG properly
-loggedservermsg 0 1 < PING :?
+insert servermsglogged : +0 MSG PING :?
log 1 > PONG :?
insert full-timeout
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
× isupport-clear
log 1 $ isupport cleared
log 1 $ isupport:CHANTYPES set to: [#&]
× conn_init_1
# expect some NOTICE and PING to process/reply during initiation
-loggedservermsg 0 1 < :*.?.net NOTICE * :*** Looking up your ident...
+insert servermsglogged : +0 MSG :*.?.net NOTICE * :*** Looking up your ident...
log 2 < (server) *** Looking up your ident...
-loggedservermsg 0 1 < :*.?.net NOTICE * :*** Looking up your hostname...
+insert servermsglogged : +0 MSG :*.?.net NOTICE * :*** Looking up your hostname...
log 2 < (server) *** Looking up your hostname...
-loggedservermsg 0 1 < :*.?.net NOTICE * :*** Found your hostname (baz.bar.foo)
+insert servermsglogged : +0 MSG :*.?.net NOTICE * :*** Found your hostname (baz.bar.foo)
log 2 < (server) *** Found your hostname (baz.bar.foo)
-loggedservermsg 0 1 < PING :?
+insert servermsglogged : +0 MSG PING :?
log 1 > PONG :?
# handle 433
-loggedservermsg 0 1 < :*.?.net 433 * foo :Nickname already in use
+insert servermsglogged : +0 MSG :*.?.net 433 * foo :Nickname already in use
log 1 $ nickname already in use, trying increment
log 1 > NICK :foo0
-loggedservermsg 0 1 < :*.?.net 433 * foo0 :Nickname already in use
+insert servermsglogged : +0 MSG :*.?.net 433 * foo0 :Nickname already in use
log 1 $ nickname already in use, trying increment
log 1 > NICK :foo1
# collect server capabilities
-loggedservermsg 0 1 < :*.?.net CAP * LS : foo bar sasl=PLAIN,EXTERNAL baz cap-notify
+insert servermsglogged : +0 MSG :*.?.net CAP * LS : foo bar sasl=PLAIN,EXTERNAL baz cap-notify
log 1 > CAP REQ :sasl
log 1 > CAP :LIST
-loggedservermsg 0 1 < :*.?.net CAP * ACK :sasl
-loggedservermsg 0 1 < :*.?.net CAP * LIST :cap-notify sasl
+insert servermsglogged : +0 MSG :*.?.net CAP * ACK :sasl
+insert servermsglogged : +0 MSG :*.?.net CAP * LIST :cap-notify sasl
log 1 $ caps:bar:data set to: []
log 1 $ caps:baz:data set to: []
log 1 $ caps:cap-notify:data set to: []
# authenticate via SASL, collect items of user identity
log 1 $ sasl_auth_state set to: [attempting]
log 1 > AUTHENTICATE :PLAIN
-loggedservermsg 0 1 < AUTHENTICATE +
+insert servermsglogged : +0 MSG AUTHENTICATE +
log 1 > AUTHENTICATE :Zm9vAGZvbwBiYXI=
-loggedservermsg 0 1 < :foo.bar.baz 900 foo1 foo1!foobarbazq@baz.bar.foo foo :You are now logged in as foo
+insert servermsglogged : +0 MSG :foo.bar.baz 900 foo1 foo1!foobarbazq@baz.bar.foo foo :You are now logged in as foo
log 1 $ users:me:nick set to: [?]
log 1 $ users:me:nick set to: [foo1]
log 1 $ users:me:user set to: [foobarbazq]
log 1 $ users:me:host set to: [baz.bar.foo]
log 1 $ sasl_account set to: [foo]
-loggedservermsg 0 1 < :foo.bar.baz 903 foo1 :SASL authentication successful
+insert servermsglogged : +0 MSG :foo.bar.baz 903 foo1 :SASL authentication successful
log 1 $ sasl_auth_state set to: [SASL authentication successful]
# finish CAP negotation, thus login procedure
log 1 > CAP :END
× conn_init_2
# of all pre-MOTD greeting messages, only process isupports
-loggedservermsg 0 1 < :foo.bar.baz 001 foo1 :Welcome to the foo.bar.baz network
-loggedservermsg 0 1 < :foo.bar.baz 002 foo1 :Your host is foo.bar.baz
-loggedservermsg 0 1 < :foo.bar.baz 003 foo1 :This server was created Jan 1 2020
-loggedservermsg 0 1 < :foo.bar.baz 004 foo1 foo.bar.baz ircserver-1.0 abc def ghi
-loggedservermsg 0 1 < :foo.bar.baz 005 foo1 ABC=DEF GHI=JKL :are supported by this server
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo1 :Welcome to the foo.bar.baz network
+insert servermsglogged : +0 MSG :foo.bar.baz 002 foo1 :Your host is foo.bar.baz
+insert servermsglogged : +0 MSG :foo.bar.baz 003 foo1 :This server was created Jan 1 2020
+insert servermsglogged : +0 MSG :foo.bar.baz 004 foo1 foo.bar.baz ircserver-1.0 abc def ghi
+insert servermsglogged : +0 MSG :foo.bar.baz 005 foo1 ABC=DEF GHI=JKL :are supported by this server
log 1 $ isupport:ABC set to: [DEF]
log 1 $ isupport:GHI set to: [JKL]
-loggedservermsg 0 1 < :foo.bar.baz 005 foo1 MNO=PQR STU=VWX Y=Z :are supported by this server
+insert servermsglogged : +0 MSG :foo.bar.baz 005 foo1 MNO=PQR STU=VWX Y=Z :are supported by this server
log 1 $ isupport:MNO set to: [PQR]
log 1 $ isupport:STU set to: [VWX]
log 1 $ isupport:Y set to: [Z]
-loggedservermsg 0 1 < :foo.bar.baz 251 foo1 :There are 10 users and 1000 invisible on 5 servers
-loggedservermsg 0 1 < :foo.bar.baz 252 foo1 7 :IRC Operators online
-loggedservermsg 0 1 < :foo.bar.baz 253 foo1 4 :unknown connection(s)
-loggedservermsg 0 1 < :foo.bar.baz 254 foo1 800 :channels formed
-loggedservermsg 0 1 < :foo.bar.baz 255 foo1 :I have 100 clients and 1 serveres
-loggedservermsg 0 1 < :foo.bar.baz 265 foo1 100 150 :Current local users 100, max 150
-loggedservermsg 0 1 < :foo.bar.baz 266 foo1 1010 1050 :Current global users 1010, max 1050
-loggedservermsg 0 1 < :foo.bar.baz 250 foo1 :Highest connection count: 151 (150 clients) (1080 connections received)
+insert servermsglogged : +0 MSG :foo.bar.baz 251 foo1 :There are 10 users and 1000 invisible on 5 servers
+insert servermsglogged : +0 MSG :foo.bar.baz 252 foo1 7 :IRC Operators online
+insert servermsglogged : +0 MSG :foo.bar.baz 253 foo1 4 :unknown connection(s)
+insert servermsglogged : +0 MSG :foo.bar.baz 254 foo1 800 :channels formed
+insert servermsglogged : +0 MSG :foo.bar.baz 255 foo1 :I have 100 clients and 1 serveres
+insert servermsglogged : +0 MSG :foo.bar.baz 265 foo1 100 150 :Current local users 100, max 150
+insert servermsglogged : +0 MSG :foo.bar.baz 266 foo1 1010 1050 :Current global users 1010, max 1050
+insert servermsglogged : +0 MSG :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)
-loggedservermsg 0 1 < :foo.bar.baz 375 foo1 :- foo.bar.baz Message of the Day -
-loggedservermsg 0 1 < :foo.bar.baz 372 foo1 :- Howdy! -
-loggedservermsg 0 1 < :foo.bar.baz 372 foo1 :- Welcome! -
-loggedservermsg 0 1 < :foo.bar.baz 372 foo1 :- (to this server) -
-loggedservermsg 0 1 < :foo.bar.baz 376 foo1 :End of /MOTD command
+insert servermsglogged : +0 MSG :foo.bar.baz 375 foo1 :- foo.bar.baz Message of the Day -
+insert servermsglogged : +0 MSG :foo.bar.baz 372 foo1 :- Howdy! -
+insert servermsglogged : +0 MSG :foo.bar.baz 372 foo1 :- Welcome! -
+insert servermsglogged : +0 MSG :foo.bar.baz 372 foo1 :- (to this server) -
+insert servermsglogged : +0 MSG :foo.bar.baz 376 foo1 :End of /MOTD command
log 1 $ motd set to: [- Howdy! -], [- Welcome! -], [- (to this server) -]
log 2 $ - Howdy! -
log 2 $ - Welcome! -
log 2 $ - (to this server) -
# collect user mode
-loggedservermsg 0 1 < :foo1 MODE foo1 :+Ziw
+insert servermsglogged : +0 MSG :foo1 MODE foo1 :+Ziw
log 1 $ users:me:modes set to: [+Ziw]
# handle bot query NOTICE
-loggedservermsg 0 1 < :SaslServ!SaslServ@services.bar.baz NOTICE foo1 :Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
+insert servermsglogged : +0 MSG :SaslServ!SaslServ@services.bar.baz NOTICE foo1 :Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
log 3 < (SaslServ) Last login from ~foobarbaz@foo.bar.baz on Jan 1 22:00:00 2021 +0000.
× during_conn
# test recoverable 432
> /nick @foo
log 1 > NICK :@foo
-loggedservermsg 0 1 < :*.?.net 432 foo1 @foo :Erroneous nickname
+insert servermsglogged : +0 MSG :*.?.net 432 foo1 @foo :Erroneous nickname
log 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
log 1 > JOIN :#test
-loggedservermsg 0 1 < :foo1!~foobarbaz@baz.bar.foo JOIN #test
+insert servermsglogged : +0 MSG :foo1!~foobarbaz@baz.bar.foo JOIN #test
log 1 $ users:me:user set to: [~foobarbaz]
-loggedservermsg 0 1 < :foo.bar.baz 332 foo1 #test :foo bar baz
+insert servermsglogged : +0 MSG :foo.bar.baz 332 foo1 #test :foo bar baz
log 1 $ channels:#test:exits cleared
-loggedservermsg 0 1 < :foo.bar.baz 333 foo1 #test bar!~bar@OLD.bar.bar 1234567890
+insert servermsglogged : +0 MSG :foo.bar.baz 333 foo1 #test bar!~bar@OLD.bar.bar 1234567890
log 1 $ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
log 4 $ bar!~bar@OLD.bar.bar set topic: foo bar baz
-loggedservermsg 0 1 < :foo.bar.baz 353 foo1 @ #test :foo1 @bar
+insert servermsglogged : +0 MSG :foo.bar.baz 353 foo1 @ #test :foo1 @bar
log 1 $ users:1:nick set to: [?]
log 1 $ users:1:nick set to: [bar]
-loggedservermsg 0 1 < :foo.bar.baz 366 foo1 #test :End of /NAMES list.
+insert servermsglogged : +0 MSG :foo.bar.baz 366 foo1 #test :End of /NAMES list.
log 1 $ channels:#test:user_ids set to: [1], [me]
log 4 $ residents: bar, foo1
# deliver PRIVMSG to channel window, update sender's user+host from metadata
-loggedservermsg 0 1 < :bar!~bar@bar.bar PRIVMSG #test :hi there
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar PRIVMSG #test :hi there
log 1 $ users:1:user set to: [~bar]
log 1 $ users:1:host set to: [bar.bar]
log 4 < [bar] hi there
# check _changing_ TOPIC message is communicated to channel window, as long as either content or who change
-loggedservermsg 0 1 < :bar!~bar@bar.bar TOPIC #test :foo bar baz
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar TOPIC #test :foo bar baz
log 1 $ channels:#test:topic set to: [Topic(what='foo bar baz', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
log 4 $ bar!~bar@bar.bar set topic: foo bar baz
-loggedservermsg 0 1 < :bar!~bar@bar.bar TOPIC #test :foo bar baz
-loggedservermsg 0 1 < :bar!~bar@bar.bar TOPIC #test :abc def ghi
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar TOPIC #test :foo bar baz
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar TOPIC #test :abc def ghi
log 1 $ channels:#test:topic set to: [Topic(what='abc def ghi', who=NickUserHost(nick='bar', user='~bar', host='bar.bar'))]
log 4 $ bar!~bar@bar.bar set topic: abc def ghi
# process non-self channel JOIN
-loggedservermsg 0 1 < :baz!~baz@baz.baz JOIN :#test
+insert servermsglogged : +0 MSG :baz!~baz@baz.baz JOIN :#test
log 1 $ users:2:nick set to: [?]
log 1 $ users:2:nick set to: [baz]
log 1 $ users:2:user set to: [~baz]
# join second channel with partial residents identity to compare distribution of resident-specific messages
> /join #testtest
log 1 > JOIN :#testtest
-loggedservermsg 0 1 < :foo1!~foobarbaz@baz.bar.foo JOIN #testtest
-loggedservermsg 0 1 < :foo.bar.baz 332 foo1 #testtest :baz bar foo
+insert servermsglogged : +0 MSG :foo1!~foobarbaz@baz.bar.foo JOIN #testtest
+insert servermsglogged : +0 MSG :foo.bar.baz 332 foo1 #testtest :baz bar foo
log 1 $ channels:#testtest:exits cleared
-loggedservermsg 0 1 < :foo.bar.baz 333 foo1 #testtest bar!~bar@OLD.bar.bar 1234567890
+insert servermsglogged : +0 MSG :foo.bar.baz 333 foo1 #testtest bar!~bar@OLD.bar.bar 1234567890
log 1 $ channels:#testtest:topic set to: [Topic(what='baz bar foo', who=NickUserHost(nick='bar', user='~bar', host='OLD.bar.bar'))]
log 5 $ bar!~bar@OLD.bar.bar set topic: baz bar foo
-loggedservermsg 0 1 < :foo.bar.baz 353 foo1 @ #testtest :foo1 baz
-loggedservermsg 0 1 < :foo.bar.baz 366 foo1 #testtest :End of /NAMES list.
+insert servermsglogged : +0 MSG :foo.bar.baz 353 foo1 @ #testtest :foo1 baz
+insert servermsglogged : +0 MSG :foo.bar.baz 366 foo1 #testtest :End of /NAMES list.
log 1 $ channels:#testtest:user_ids set to: [2], [me]
log 5 $ residents: baz, foo1
# handle query window with known user
-loggedservermsg 0 1 < :baz!~baz@baz.baz PRIVMSG foo1 :hi there
+insert servermsglogged : +0 MSG :baz!~baz@baz.baz PRIVMSG foo1 :hi there
log 6 < [baz] hi there
> /privmsg baz hello, how is it going
log 1 > PRIVMSG baz :hello, how is it going
log 6 > [foo1] hello, how is it going
-loggedservermsg 0 1 < :baz!~baz@baz.baz PRIVMSG foo1 :fine!
+insert servermsglogged : +0 MSG :baz!~baz@baz.baz PRIVMSG foo1 :fine!
log 6 < [baz] fine!
# handle failure to query absent user
> /privmsg barbar hello!
log 1 > PRIVMSG barbar :hello!
log 7 > [foo1] hello!
-loggedservermsg 0 1 < :*.?.net 401 foo1 barbar :No such nick/channel
+insert servermsglogged : +0 MSG :*.?.net 401 foo1 barbar :No such nick/channel
log 7 $ barbar not online
# handle non-self renaming
-loggedservermsg 0 1 < :baz!~baz@baz.baz NICK :bazbaz
+insert servermsglogged : +0 MSG :baz!~baz@baz.baz NICK :bazbaz
log 1 $ users:2:nick set to: [bazbaz]
log 4,5,6 $ baz!~baz@baz.baz renames bazbaz
# handle non-self PART in one of two inhabited channels, preserve identity into re-JOIN
-loggedservermsg 0 1 < :bazbaz!~baz@baz.baz PART :#test
+insert servermsglogged : +0 MSG :bazbaz!~baz@baz.baz PART :#test
log 1 $ channels:#test:exits:2 set to: [P]
log 1 $ channels:#test:user_ids set to: [1], [me]
log 4 $ bazbaz!~baz@baz.baz parts
log 1 $ channels:#test:exits:2 cleared
-loggedservermsg 0 1 < :bazbaz!~baz@baz.baz JOIN :#test
+insert servermsglogged : +0 MSG :bazbaz!~baz@baz.baz JOIN :#test
log 1 $ channels:#test:user_ids set to: [1], [2], [me]
log 4 $ bazbaz!~baz@baz.baz joins
# handle non-self PART in only inhabited channel, lose identity, re-join as new identity
-loggedservermsg 0 1 < :bar!~bar@bar.bar PART :#test
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar PART :#test
log 1 $ channels:#test:exits:1 set to: [P]
log 1 $ channels:#test:user_ids set to: [2], [me]
log 4 $ bar!~bar@bar.bar parts
log 1 $ channels:#test:exits:1 cleared
log 1 $ users:1 cleared
-loggedservermsg 0 1 < :bar!~bar@bar.bar JOIN :#test
+insert servermsglogged : +0 MSG :bar!~bar@bar.bar JOIN :#test
log 1 $ users:3:nick set to: [?]
log 1 $ users:3:nick set to: [bar]
log 1 $ users:3:user set to: [~bar]
log 1 $ channels:#test:user_ids set to: [2], [3], [me]
log 4 $ bar!~bar@bar.bar joins
# handle non-self QUIT
-loggedservermsg 0 1 < :bazbaz!~baz@baz.baz QUIT :Client Quit
+insert servermsglogged : +0 MSG :bazbaz!~baz@baz.baz QUIT :Client Quit
log 1 $ users:2:exit_msg set to: [QClient Quit]
log 6 $ bazbaz!~baz@baz.baz quits: Client Quit
log 1 $ channels:#test:exits:2 set to: [QClient Quit]
log 1 $ channels:#testtest:exits:2 cleared
log 1 $ users:2 cleared
# handle self-PART: clear channel, and its squatters
-loggedservermsg 0 1 < :foo1!~foobarbaz@baz.bar.foo PART :#test
+insert servermsglogged : +0 MSG :foo1!~foobarbaz@baz.bar.foo PART :#test
log 1 $ channels:#test:exits:me set to: [P]
log 1 $ channels:#test:user_ids set to: [3]
log 4 $ foo1!~foobarbaz@baz.bar.foo parts
log 1 $ channels:#test cleared
log 1 $ users:3 cleared
# handle lack of implementation
-loggedservermsg 0 1 < foo bar baz
+insert servermsglogged : +0 MSG foo bar baz
log 1 $ No handler implemented for: foo bar baz
log 2,3,4,5,6,7 $ No handler implemented for: foo bar baz
# handle /disconnect, clear all
> /disconnect
log 1 > QUIT :ircplom says bye
-loggedservermsg 0 1 < :foo1!~foobarbaz@baz.bar.foo QUIT :Client Quit
+insert servermsglogged : +0 MSG :foo1!~foobarbaz@baz.bar.foo QUIT :Client Quit
log 1 $ users:me:exit_msg set to: [QClient Quit]
log 3,6,7 $ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
log 1 $ channels:#testtest:exits:me set to: [QClient Quit]
log 1 $ channels:#testtest:user_ids cleared
log 5 $ foo1!~foobarbaz@baz.bar.foo quits: Client Quit
log 1 $ channels:#testtest:exits:me cleared
-loggedservermsg 0 1 < ERROR :Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]
+insert servermsglogged : +0 MSG ERROR :Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]
log 1 $ connection_state set to: [Closing link: (~foobarbaz@baz.bar.foo) [Quit: ircplom says bye]]
insert isupport-clear
log 1 $ caps cleared
insert conn_init_0 7:10 +8
log 8 > USER foo 0 * :foo
log 8 > NICK :?foo
-loggedservermsg 1 8 < :*.?.net 432 * ?foo :Erroneous nickname
+servermsg 1 :*.?.net 432 * ?foo :Erroneous nickname
+log 8 < :*.?.net 432 * ?foo :Erroneous nickname
insert disconnect :2 +8
log 9 $ DISCONNECTED
log 8 $ nickname refused for bad format, giving up
× line-cal
line 0 on_black,bright_white 20§§-§§-§§ §§
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
× history_0
insert line-cal : +0
insert line-invalid-prompt-command : +1 ? not prefixed by /§§
insert lines-status-prompt-start : +22 X123456789X123456789X =========([0] 1 (2:7)
# check new lines growing in other window, one of which long enough to wrap, to be re-start count in status (with wrapped only as single)
-loggedservermsg 0 1 < PING :?
+insert servermsglogged : +0 MSG PING :?
log 1 > PONG :?
-loggedservermsg 0 1 < PING :9 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+insert servermsglogged : +0 MSG PING :9 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
log 1 > PONG :9 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
insert history_0 11:28 +0
insert line-bookmark : +17
### # check that growth below scroll does not by itself re-position bookmark in history
> /window.history.scroll up
-loggedservermsg 0 1 < PING :foo
+insert servermsglogged : +0 MSG PING :foo
log 1 > PONG :foo
insert lines-empty :6
insert history_1 0:15 +6
# check that growing lines below scroll in other preserves non-bottom bookmark (left in sight on previous window leave)
> /window 0
-loggedservermsg 0 1 < PING :bar
+insert servermsglogged : +0 MSG PING :bar
log 1 > PONG :bar
insert history_0 11:32 +0
insert line-bookmark : +21
insert line-scrolldown : +21 XXXXXX [12] v
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:4)] (2:7)
> /window 0
-loggedservermsg 0 1 < PING :baz
+insert servermsglogged : +0 MSG PING :baz
log 1 > PONG :baz
insert history_0 11:32 +0
insert line-bookmark : +21
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
# check log growth beyond max depth only remarkable after scrolling up to limit
-loggedservermsg 0 1 < PING :0
+insert servermsglogged : +0 MSG PING :0
log 1 > PONG :0
insert history_1 12:25 +0
insert line-bookmark : +13
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
# check cut-off log growth seen from topmost scroll not affecting scrolldown count, but unread-lines status
-loggedservermsg 0 1 < PING :0
+insert servermsglogged : +0 MSG PING :0
log 1 > PONG :0
insert lines-empty :20
insert history_1 3:4 +20
insert history_0 11:32 +0
insert line-bookmark : +21
insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:2) (2:7)
-loggedservermsg 0 1 < PING :1
+insert servermsglogged : +0 MSG PING :1
log 1 > PONG :1
-loggedservermsg 0 1 < PING :2
+insert servermsglogged : +0 MSG PING :2
log 1 > PONG :2
-loggedservermsg 0 1 < PING :3
+insert servermsglogged : +0 MSG PING :3
log 1 > PONG :3
-loggedservermsg 0 1 < PING :4
+insert servermsglogged : +0 MSG PING :4
log 1 > PONG :4
-loggedservermsg 0 1 < PING :5
+insert servermsglogged : +0 MSG PING :5
log 1 > PONG :5
-loggedservermsg 0 1 < PING :6
+insert servermsglogged : +0 MSG PING :6
log 1 > PONG :6
-loggedservermsg 0 1 < PING :7
+insert servermsglogged : +0 MSG PING :7
log 1 > PONG :7
-loggedservermsg 0 1 < PING :8
+insert servermsglogged : +0 MSG PING :8
log 1 > PONG :8
-loggedservermsg 0 1 < PING :9
+insert servermsglogged : +0 MSG PING :9
log 1 > PONG :9
-loggedservermsg 0 1 < PING :10
+insert servermsglogged : +0 MSG PING :10
log 1 > PONG :10
-loggedservermsg 0 1 < PING :11
+insert servermsglogged : +0 MSG PING :11
log 1 > PONG :11
-loggedservermsg 0 1 < PING :12
+insert servermsglogged : +0 MSG PING :12
log 1 > PONG :12
-loggedservermsg 0 1 < PING :13
+insert servermsglogged : +0 MSG PING :13
log 1 > PONG :13
-loggedservermsg 0 1 < PING :14
+insert servermsglogged : +0 MSG PING :14
log 1 > PONG :14
-loggedservermsg 0 1 < PING :15
+insert servermsglogged : +0 MSG PING :15
log 1 > PONG :15
insert history_0 11:32 +0
insert line-bookmark : +21
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
# check bookmark remains absent with log growing while scrolled to bottom, …
-loggedservermsg 0 1 < PING :16
+insert servermsglogged : +0 MSG PING :16
log 1 > PONG :16
insert history_1 43:63 +0
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
insert history_1 35:54 +2
insert line-scrolldown : +21 XXXXXX [11] v
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
-loggedservermsg 0 1 < PING :17
+insert servermsglogged : +0 MSG PING :17
log 1 > PONG :17
insert lines-empty :4
insert history_1 37:54 +4
insert history_1 37:54 +2
insert line-scrolldown : +21 XXXXXX [11] v
insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
-loggedservermsg 0 1 < PING :18
+insert servermsglogged : +0 MSG PING :18
log 1 > PONG :18
-loggedservermsg 0 1 < PING :19
+insert servermsglogged : +0 MSG PING :19
log 1 > PONG :19
-loggedservermsg 0 1 < PING :20
+insert servermsglogged : +0 MSG PING :20
log 1 > PONG :20
-loggedservermsg 0 1 < PING :21
+insert servermsglogged : +0 MSG PING :21
log 1 > PONG :21
-loggedservermsg 0 1 < PING :22
+insert servermsglogged : +0 MSG PING :22
log 1 > PONG :22
-loggedservermsg 0 1 < PING :23
+insert servermsglogged : +0 MSG PING :23
log 1 > PONG :23
-loggedservermsg 0 1 < PING :24
+insert servermsglogged : +0 MSG PING :24
log 1 > PONG :24
-loggedservermsg 0 1 < PING :25
+insert servermsglogged : +0 MSG PING :25
log 1 > PONG :25
-loggedservermsg 0 1 < PING :26
+insert servermsglogged : +0 MSG PING :26
log 1 > PONG :26
-loggedservermsg 0 1 < PING :27
+insert servermsglogged : +0 MSG PING :27
log 1 > PONG :27
-loggedservermsg 0 1 < PING :28
+insert servermsglogged : +0 MSG PING :28
log 1 > PONG :28
-loggedservermsg 0 1 < PING :29
+insert servermsglogged : +0 MSG PING :29
log 1 > PONG :29
-loggedservermsg 0 1 < PING :30
+insert servermsglogged : +0 MSG PING :30
log 1 > PONG :30
-loggedservermsg 0 1 < PING :31
+insert servermsglogged : +0 MSG PING :31
log 1 > PONG :31
-loggedservermsg 0 1 < PING :32
+insert servermsglogged : +0 MSG PING :32
log 1 > PONG :32
insert lines-empty :20
insert history_1 67:68 +20
+× servermsglogged
+servermsg 0 MSG
+log 1 < MSG
+
+×
+
> /connect foo.bar.baz foo bar:baz
log 1 $ isupport cleared
log 1 $ isupport:CHANTYPES set to: [#&]
log 1 > USER baz 0 * :bar
log 1 > NICK :foo
> /window 1
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :Welcome to the foo.bar.baz network
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :Welcome to the foo.bar.baz network
log 1 $ users:me:nick set to: [?]
log 1 $ users:me:nick set to: [foo]
# check full line not wrapped
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :6789 123456789 123456789 123456789 12345678 0
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :6789 123456789 123456789 123456789 12345678 0
line 21 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :6789 123456789 123456789 123456789 12345678 0§§
# check wrap if last space-separated item one char too long
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678 01
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678 01
line 20 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678§§
line 21 on_black,bright_white 01§§
# check wrap if item starts right after width-final space
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 123456789 1
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 123456789 1
line 20 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 123456789§§
line 21 on_black,bright_white 1§§
# check wrap if item starts right after space after item extending to end of width
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890 2
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890 2
line 20 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890§§
line 21 on_black,bright_white 2§§
# check wrap if item starts right after double-space after item extending to end of width
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890 3
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890 3
line 20 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567890§§
line 21 on_black,bright_white 3§§
# check wrap on item too large to fit into screen width minus indent
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_2345678
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_2345678
line 19 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo§§
line 20 on_black,bright_white :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_234567§§
line 21 on_black,bright_white 8
# check wrapping calculation on double-width character (tbh not much of a test since the tester itself counts specifically this char as two, so it's pretty much the same as above testing with a sequence of two ASCII chars; mostly just ensures that the wrapping code relies on Terminal.length_to_term)
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567 💓
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567 💓
line 21 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 1234567 💓§§
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678 💓
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678 💓
line 20 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo :456789 123456789 123456789 123456789 12345678§§
line 21 on_black,bright_white 💓§§
-loggedservermsg 0 1 < :foo.bar.baz 001 foo :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_23456💓
+insert servermsglogged : +0 MSG :foo.bar.baz 001 foo :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_23456💓
line 19 on_black,bright_white < §§:§§:§§ :foo.bar.baz 001 foo§§
line 20 on_black,bright_white :2345678_1_2345678_2_2345678_3_2345678_4_2345678_5_2345678_6_2345678_7_23456§§
line 21 on_black,bright_white 💓§§