home · contact · privacy
Extend testing insert command with string replacement possibility.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 7 Nov 2025 17:38:59 +0000 (18:38 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 7 Nov 2025 17:38:59 +0000 (18:38 +0100)
src/ircplom/testing.py
src/tests/_timeout_retries.test
src/tests/connect_disconnect_legalities.test
src/tests/error_disconnects.test
src/tests/pingpong.test
src/tests/test.test
src/tests/tui_draw.test

index 6b4ab63ecfa18ee83683aab4c9eb3188bffb25ca..1835be99df488f7274cfb630c3bd2fa939edb897 100644 (file)
@@ -33,7 +33,7 @@ _TOK_IDX_LOGSRVRMSG = 's'
 _TOK_IDX_REPEAT = 'r'
 
 _SIGNATURE_FOR_CMD = {
-    _MARK_INSERT: (3, 2),
+    _MARK_INSERT: (5, 2),
     _MARK_LOG: (2, 0),
     _MARK_LOGSRVRMSG: (3, 0),
     _MARK_PROMPT: (1, None),
@@ -226,16 +226,17 @@ class _Playbook:
                    fragments: dict[str, tuple[tuple[str, str], ...]],
                    **__
                    ) -> list[tuple[str, str]]:
-            candidates = [
-                    [_SEP_2.join((index_str, _TOK_IDX_REPEAT, sub_index_str)),
-                     line]
-                    for sub_index_str, line in fragments[insert_args[0]]]
-            if len(insert_args) >= 2:
+
+            def crop_to_range(range_str: str) -> None:
                 idx_in, idx_out = ((int(val) if val else None)
-                                   for val in insert_args[1].split(_SEP_2))
-                candidates = candidates[idx_in:idx_out]
-            if len(insert_args) >= 3:
-                n_bump = int(insert_args[2])
+                                   for val in range_str.split(_SEP_2))
+                candidates[:] = candidates[idx_in:idx_out]
+
+            def replace_pattern(to_replace: str, replacement: str) -> None:
+                candidates[:] = [[c[0], c[1].replace(to_replace, replacement)]
+                                 for c in candidates]
+
+            def bump_int_fields(n_bump: int) -> None:
                 to_bump = []
                 start_offset: Optional[int] = None
                 for candidate in candidates:
@@ -266,6 +267,18 @@ class _Playbook:
                                                     for n in cmd_arg)
                                         or ',']
                     candidate[1] = _SEP_0.join(to_join)
+
+            assert len(insert_args) in (1, 2, 3, 5), (index_str, insert_args)
+            candidates = [
+                    [_SEP_2.join((index_str, _TOK_IDX_REPEAT, sub_index_str)),
+                     line]
+                    for sub_index_str, line in fragments[insert_args[0]]]
+            if len(insert_args) >= 2:
+                crop_to_range(insert_args[1])
+            if len(insert_args) >= 5:
+                replace_pattern(*insert_args[3:5])
+            if len(insert_args) >= 3:
+                bump_int_fields(int(insert_args[2]))
             return [(c[0], c[1]) for c in candidates]
 
         def expand_inserts() -> None:
@@ -455,7 +468,7 @@ class TestingClientTui(ClientTui):
             **kwargs
             ) -> None:
         def test_after(cmd_name: str, args: tuple[str, ...], ret) -> None:
-            assert cmd_name == _MARK_LOG, f'WANTED {_MARK_LOG}, GOT {cmd_name}'
+            assert cmd_name == _MARK_LOG, f'WANTED {_MARK_LOG} [{ret}]'
             win_ids, logged = ret
             fmt, time_str, msg_sans_time = logged.split(' ', maxsplit=2)
             msg_sans_time = fmt + ' ' + msg_sans_time
index 2492696000a930ef2e89d0cbcfd566dc10c80eb7..9f7517d7ef61376df897de1a7732c978038e62e0 100644 (file)
@@ -10,6 +10,7 @@ log 1 $ caps cleared
 log 1 $ users cleared
 log 1 $ channels cleared
 log , $ DISCONNECTED
+log 1 $ hostname set to: [?]
 
 × identifiers
 log 2 $ - nickname: foo
@@ -17,24 +18,33 @@ log 2 $ - realname: baz
 log 2 $ - username: foobarbazquux
 log 2 $ - password: bar
 
-× connecting
-log 1 $ connection_state set to: [connecting]
+× connection_state
+log 1 $ connection_state set to: [?]
+
+× attempting-foobarbaz
+insert connection_state : +1 ? connecting
+log 2 $ attempting connection to foo.bar.baz:§§ identifying with …
+
+× attempting-bazbarfoo
+insert connection_state : +3 ? connecting
+log 4 $ attempting connection to baz.bar.foo:§§ identifying with …
 
 × fake-testing-timeout
-log 1 $ connection_state set to: [failed to connect: FAKE TESTING TIMEOUT]
+insert connection_state : +1 ? failed to connect: FAKE TESTING TIMEOUT
+insert retry-in : +1 ? §§
 
-× retry-in-1
-log 1 $ will retry connecting in 1 seconds
+× port
+log 1 $ port set to: [§]
 
-× port-10000-w-context
+× conn-config
 insert identifiers : +2
-log 1 $ port set to: [10000]
-insert fake-testing-timeout : +1
+insert port : +1 § ?
 
-× port-10001
-log 1 $ port set to: [10001]
+× retry-in
+log 1 $ will retry connecting in ? seconds
 
 × conns-init
+insert port : +1 § §§
 log 1 $ nick_wanted set to: [foo]
 log 1 $ user_wanted set to: [foobarbazquux]
 log 1 $ realname set to: [baz]
@@ -42,7 +52,7 @@ log 1 $ password set to: [bar]
 
 × conn
 insert identifiers : +2
-log 1 $ connection_state set to: [connected]
+insert connection_state : +1 ? connected
 log 2 $ CONNECTED
 log 1 > CAP LS :302
 log 1 > USER foobarbazquux 0 * :baz
@@ -54,34 +64,24 @@ log 1 > NICK :foo
 # the TestingClient meanwhile will decrement any port of that range by 1 after
 # each started connection attempt
 > /connect foo.bar.baz:10003 foo:bar baz:foobarbazquux
-insert clientwin-init
-log 1 $ hostname set to: [foo.bar.baz]
-log 1 $ port set to: [10003]
-insert conns-init
+insert clientwin-init : +1 ? foo.bar.baz
+insert conns-init : +1 §§ 10003
 
 # check increase of retry waits
-insert connecting
-log 2 $ attempting connection to foo.bar.baz:10003 identifying with …
-insert identifiers
-log 1 $ port set to: [10002]
-insert fake-testing-timeout
-insert retry-in-1
+insert attempting-foobarbaz : +1 §§ 10003
+insert conn-config : +1 ? 10002
+insert fake-testing-timeout : +1 §§ 1
 #
-insert connecting
-log 2 $ attempting connection to foo.bar.baz:10002 identifying with …
-insert identifiers
-insert port-10001
-insert fake-testing-timeout
-log 1 $ will retry connecting in 2 seconds
+insert attempting-foobarbaz : +1 §§ 10002
+insert conn-config : +1 ? 10001
+insert fake-testing-timeout : +1 §§ 2
 #
-insert connecting
-log 2 $ attempting connection to foo.bar.baz:10001 identifying with …
-insert port-10000-w-context
-log 1 $ will retry connecting in 4 seconds
+insert attempting-foobarbaz : +1 §§ 10001
+insert conn-config : +1 ? 10000
+insert fake-testing-timeout : +1 §§ 4
 
 # check connecting works with TestingClient port finally reduced to 10000
-insert connecting
-log 2 $ attempting connection to foo.bar.baz:10000 identifying with …
+insert attempting-foobarbaz : +1 §§ 10000
 insert conn
 
 # check retry chain also started by in-connection timeout
@@ -89,11 +89,11 @@ servermsg 0 timeout
 log 1 > PING :what's up?
 servermsg 0 timeout
 servermsg 0 no timely PONG from server
-log 1 $ connection_state set to: [broken: no timely PONG from server]
+insert connection_state : +1 ? broken: no timely PONG from server
 insert isupport-clear
-log 1 $ connection_state set to: []
+insert connection_state : +1 ? 
 log 2 $ DISCONNECTED
-insert retry-in-1
+insert retry-in : +1 ? 1
 
 # check /disconnect aborts retry chain
 > /window 1
@@ -103,20 +103,16 @@ wait 1
 
 # connect to second server to check timed auto-retries don't activate after manual intervention
 > /connect baz.bar.foo:10001 foo:bar baz:foobarbazquux
-insert clientwin-init : +3
-log 3 $ hostname set to: [baz.bar.foo]
-insert port-10001 : +3
-insert conns-init : +3
-insert connecting : +3
-log 4 $ attempting connection to baz.bar.foo:10001 identifying with …
-insert port-10000-w-context : +3
-insert retry-in-1 : +3
+insert clientwin-init : +3 ? baz.bar.foo
+insert conns-init : +3 §§ 10001
+insert attempting-bazbarfoo : +3 §§ 10001
+insert conn-config : +3 ? 10000
+insert fake-testing-timeout : +3 §§ 1
 
 # during retry-wait /reconnect, then wait announced duration to check nothing else happens
 > /window 3
 > /reconnect
-insert connecting : +3
-log 4 $ attempting connection to baz.bar.foo:10000 identifying with …
+insert attempting-bazbarfoo : +3 §§ 10000
 insert conn : +3
 wait 1
 
index df08df89171a6acea6bc6efe33f2a06de07a52b0..bf8cd83c2174bc50f625219b8ecebaf0126a5d3c 100644 (file)
@@ -3,6 +3,7 @@ log 1 $ isupport cleared
 log 1 $ isupport:CHANTYPES set to: [#&]
 log 1 $ isupport:PREFIX set to: [(ov)@+]
 log 1 $ isupport:USERLEN set to: [10]
+
 × connecting
 log 1 $ connection_state set to: [connecting]
 log 2 $ attempting connection to foo.bar.baz:6697 identifying with …
@@ -15,10 +16,12 @@ log 2 $ CONNECTED
 log 1 > CAP LS :302
 log 1 > USER baz 0 * :bar
 log 1 > NICK :foo
+
 × disconnecting
 insert isupport-clear
 log 1 $ connection_state set to: []
 log 2 $ DISCONNECTED
+
 ×
 
 # to prepare, initiate connection
index 247d4f38bc0638b2b35f54e9655c751c88853c2c..449ede086f2ead3b906619ecfcbf576c7c9c285a 100644 (file)
@@ -3,6 +3,7 @@ log 1 $ isupport cleared
 log 1 $ isupport:CHANTYPES set to: [#&]
 log 1 $ isupport:PREFIX set to: [(ov)@+]
 log 1 $ isupport:USERLEN set to: [10]
+
 × connecting
 log 1 $ connection_state set to: [connecting]
 log 2 $ attempting connection to foo.bar.baz:6697 identifying with …
@@ -15,6 +16,7 @@ log 2 $ CONNECTED
 log 1 > CAP LS :302
 log 1 > USER baz 0 * :bar
 log 1 > NICK :foo
+
 × disconnecting
 insert isupport-clear
 log 1 $ connection_state set to: []
@@ -22,9 +24,16 @@ log 2 $ DISCONNECTED
 × reconnect
 > /reconnect
 insert connecting
+
 × disconnect-with-retry
 insert disconnecting
 log 1 $ will retry connecting in 1 seconds
+
+× reconnect-error-logged
+insert reconnect
+loggedservermsg 0 1 < ERROR :XXX
+log 1 $ connection_state set to: [XXX]
+
 ×
 
 # to prepare first test, initiate connected state
@@ -49,19 +58,11 @@ insert disconnecting
 
 # test ERROR regex (non-)matches
 > /window 1
-insert reconnect
-loggedservermsg 0 1 < ERROR :Closing link: (this should not match)
-log 1 $ connection_state set to: [Closing link: (this should not match)]
+insert reconnect-error-logged : +0 XXX Closing link: (this should not match)
 insert disconnecting
-insert reconnect
-loggedservermsg 0 1 < ERROR :Closing link: (Connection timed out)
-log 1 $ connection_state set to: [Closing link: (Connection timed out)]
+insert reconnect-error-logged : +0 XXX Closing link: (Connection timed out)
 insert disconnect-with-retry
-insert reconnect
-loggedservermsg 0 1 < ERROR :closing Link: (connection timed out)
-log 1 $ connection_state set to: [closing Link: (connection timed out)]
+insert reconnect-error-logged : +0 XXX closing Link: (connection timed out)
 insert disconnect-with-retry
-insert reconnect
-loggedservermsg 0 1 < ERROR :Closing link: (Ping timeout: 240 seconds)
-log 1 $ connection_state set to: [Closing link: (Ping timeout: 240 seconds)]
+insert reconnect-error-logged : +0 XXX Closing link: (Ping timeout: 240 seconds)
 insert disconnect-with-retry
index 821f92cae90d2819fae0d8c2ab4f5762663874f9..ed3309cd11b3feba0a8c9bab6407d0a982af9f04 100644 (file)
@@ -63,7 +63,5 @@ insert full-timeout
 # on re-connect, ensure timer cleared, i.e. only 2nd time-out will disconnect
 > /window 1
 > /reconnect
-insert conn :7
-log 2 $ CONNECTED
-insert conn 8:
+insert conn
 insert full-timeout
index bc216b8aa9c6b77217ade5791f46176be2535b76..5e2d446ee5fd38a37751c49bc66b1a6930a60686 100644 (file)
@@ -379,6 +379,9 @@ log 10 $ connection_state set to: [broken: FAKE_IRC_CONN_ABORT_EXCEPTION]
 insert disconnect :2 +10
 log 11 $ DISCONNECTED
 log 10 $ will retry connecting in 1 seconds
+> /window 10
+> /disconnect
+log 10 $ already disconnected, stopped connecting attempts
 
 # zero unread-lines counts in status line so it won't explode simulated screen
 > /window 2
index 440d2c3cf9b40bb80a731787f3f7ce61d9469270..b52bb94f69b23f4501fea4c77b9682378b7549ef 100644 (file)
@@ -25,288 +25,233 @@ insert lines-empty-1 : +19
 insert lines-empty-1 : +20
 insert lines-empty-1 : +21
 
-× prompt-empty
+× lines-prompt-empty
 line 23 on_black,bright_white > § §§
 line 23 on_black,bright_white,reverse §§ §
 
-× bookmark
+× line-bookmark
 line 0 on_black,bright_white --------------------------------------------------------------------------------§§
 
-× scrolldown-1
-line 21 on_black,bright_white,reverse vvv [1] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-2
-line 21 on_black,bright_white,reverse vvv [2] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-3
-line 21 on_black,bright_white,reverse vvv [3] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-4
-line 21 on_black,bright_white,reverse vvv [4] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-6
-line 21 on_black,bright_white,reverse vvv [6] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-7
-line 21 on_black,bright_white,reverse vvv [7] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-8
-line 21 on_black,bright_white,reverse vvv [8] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-9
-line 21 on_black,bright_white,reverse vvv [9] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-10
-line 21 on_black,bright_white,reverse vvv [10] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-11
-line 21 on_black,bright_white,reverse vvv [11] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-12
-line 21 on_black,bright_white,reverse vvv [12] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-13
-line 21 on_black,bright_white,reverse vvv [13] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-14
-line 21 on_black,bright_white,reverse vvv [14] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-18
-line 21 on_black,bright_white,reverse vvv [18] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-19
-line 21 on_black,bright_white,reverse vvv [19] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-22
-line 21 on_black,bright_white,reverse vvv [22] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-25
-line 21 on_black,bright_white,reverse vvv [25] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-× scrolldown-29
-line 21 on_black,bright_white,reverse vvv [29] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
-
-
-× status-[0]-prompt
-line 22 on_black,bright_white :start)=====================================================================([0]§§
-insert prompt-empty
-× status-[0]-1-(2:7)-prompt
-line 22 on_black,bright_white :start)=============================================================([0] 1 (2:7)§§
-insert prompt-empty
-× status-[0]-1:2-(2:7)-prompt
-line 22 on_black,bright_white :start)=========================================================([0] (1:2) (2:7)§§
-insert prompt-empty
-× status-0-[1:2]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==============================================(0 [(1:2)] (2:7)§§
-insert prompt-empty
-× status-[0]-1:4-(2:7)-prompt
-line 22 on_black,bright_white :start)=========================================================([0] (1:4) (2:7)§§
-insert prompt-empty
-× status-0-[1:4]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==============================================(0 [(1:4)] (2:7)§§
-insert prompt-empty
-× status-[0]-1:6-(2:7)-prompt
-line 22 on_black,bright_white :start)=========================================================([0] (1:6) (2:7)§§
-insert prompt-empty
-× status-0-[1:6]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==============================================(0 [(1:6)] (2:7)§§
-insert prompt-empty
-× status-0-[1:7]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==============================================(0 [(1:7)] (2:7)§§
-insert prompt-empty
-× status-0-[1:18]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)=============================================(0 [(1:18)] (2:7)§§
-insert prompt-empty
-× status-[0]-1:29-(2:7)-prompt
-line 22 on_black,bright_white :start)========================================================([0] (1:29) (2:7)§§
-insert prompt-empty
-× status-0-[1:29]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)=============================================(0 [(1:29)] (2:7)§§
-insert prompt-empty
-× status-[0]-1:32-(2:7)-prompt
-line 22 on_black,bright_white :start)========================================================([0] (1:32) (2:7)§§
-insert prompt-empty
-× status-0-[1]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==================================================(0 [1] (2:7)§§
-insert prompt-empty
-× status-[0:1]-prompt
-line 22 on_black,bright_white :start)=================================================================([(0:1)]§§
-insert prompt-empty
-× status-[0:1]-1-(2:7)-prompt
-line 22 on_black,bright_white :start)=========================================================([(0:1)] 1 (2:7)§§
-insert prompt-empty
-× status-0:1-[1]-(2:7)-prompt
-line 22 on_black,bright_white foo.bar.baz:debug)==============================================((0:1) [1] (2:7)§§
-insert prompt-empty
-× status-[0:1]-1:19-(2:7)-prompt
-line 22 on_black,bright_white :start)====================================================([(0:1)] (1:19) (2:7)§§
-insert prompt-empty
-× status-[0:3]-prompt
-line 22 on_black,bright_white :start)=================================================================([(0:3)]§§
-insert prompt-empty
-× status-[0:12]-prompt
-line 22 on_black,bright_white :start)================================================================([(0:12)]§§
-insert prompt-empty
+× line-scrolldown
+line 21 on_black,bright_white,reverse vvv XXXXXXvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv§§
 
-× history_0
+× lines-status-prompt-start
+line 22 on_black,bright_white :start)====================================================X123456789X123456789X§§
+insert lines-prompt-empty
+
+× lines-status-prompt-foobarbaz
+line 22 on_black,bright_white foo.bar.baz:debug)=========================================X123456789X123456789X§§
+insert lines-prompt-empty
+
+× line-invalid-prompt-command
+line 0 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: ?
+
+× line-invalid-prompt-command-unknown
+line 0 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /? unknown§§
+
+× line-ping
+line 0 on_black,bright_white < §§:§§:§§ PING :?
+
+× line-pong
+line 0 on_black,bright_green > §§:§§:§§ PONG :?
+
+× line-tui-log
+line 0 on_black,bright_cyan # §§:§§:§§ ?§§
+
+× line-bright-red-bold
+line 0 on_black,bright_red,bold ?§§
+
+× line-bright-white
+line 0 on_black,bright_white ?§§
+
+× line-bright-green
+line 0 on_black,bright_green ?§§
+
+× line-server-log
+line 0 on_black,bright_yellow $ §§:§§:§§ ?§§§
+
+× line-client-msg
+line 0 on_black,bright_green > §§:§§:§§ ?§§
+
+× line-cal
 line 0 on_black,bright_white 20§§-§§-§§ §§
-line 1 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: not prefixed by / §§
-line 2 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /foo unknown §§
-line 3 on_black,bright_cyan # §§:§§:§§ commands available in this window:§§
-line 4 on_black,bright_cyan # §§:§§:§§   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]§§
-line 5 on_black,bright_cyan # §§:§§:§§   /help§§
-line 6 on_black,bright_cyan # §§:§§:§§   /list§§
-line 7 on_black,bright_cyan # §§:§§:§§   /prompt_enter§§
-line 8 on_black,bright_cyan # §§:§§:§§   /quit§§
-line 9 on_black,bright_cyan # §§:§§:§§   /window TOWARDS§§
-line 10 on_black,bright_cyan # §§:§§:§§   /window.history.scroll DIRECTION§§
-line 11 on_black,bright_cyan # §§:§§:§§   /window.paste
-line 12 on_black,bright_cyan # §§:§§:§§   /window.prompt.backspace§§
-line 13 on_black,bright_cyan # §§:§§:§§   /window.prompt.move_cursor DIRECTION§§
-line 14 on_black,bright_cyan # §§:§§:§§   /window.prompt.scroll DIRECTION§§
-line 15 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /0 unknown§§
-line 16 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /1 unknown§§
-line 17 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /2 unknown§§
-line 18 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /3 unknown§§
-line 19 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /4 unknown§§
-line 20 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /5 unknown§§
-line 21 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /6 unknown§§
-line 22 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /7 unknown§§
-line 23 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /foo_0123456789_0123456789_0123456789 unknown§§
-line 24 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /foo_0123456789_0123456789_0123456789_§§
-line 25 on_black,bright_red,bold    unknown§§
-line 26 on_black,bright_red,bold # §§:§§:§§ invalid prompt command: /bar_0123456789_0123456789_0123456789_§§
-line 27 on_black,bright_red,bold    unknown§§
-line 28 on_black,bright_cyan # §§:§§:§§ windows available via /window:§§
-line 29 on_black,bright_cyan # §§:§§:§§   0) :start§§
-line 30 on_black,bright_cyan # §§:§§:§§   1) foo.bar.baz:debug§§
-line 31 on_black,bright_cyan # §§:§§:§§   2) foo.bar.baz:server§§
+
+× history_0
+insert line-cal : +0
+insert line-invalid-prompt-command : +1 ? not prefixed by /§§
+insert line-invalid-prompt-command-unknown : +2 ? foo
+insert line-tui-log : +3 ? commands available in this window:
+insert line-tui-log : +4 ?   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]§§
+insert line-tui-log : +5 ?   /help§§
+insert line-tui-log : +6 ?   /list§§
+insert line-tui-log : +7 ?   /prompt_enter§§
+insert line-tui-log : +8 ?   /quit§§
+insert line-tui-log : +9 ?   /window TOWARDS§§
+insert line-tui-log : +10 ?   /window.history.scroll DIRECTION§§
+insert line-tui-log : +11 ?   /window.paste
+insert line-tui-log : +12 ?   /window.prompt.backspace§§
+insert line-tui-log : +13 ?   /window.prompt.move_cursor DIRECTION§§
+insert line-tui-log : +14 ?   /window.prompt.scroll DIRECTION§§
+insert line-invalid-prompt-command-unknown : +15 ? 0
+insert line-invalid-prompt-command-unknown : +16 ? 1
+insert line-invalid-prompt-command-unknown : +17 ? 2
+insert line-invalid-prompt-command-unknown : +18 ? 3
+insert line-invalid-prompt-command-unknown : +19 ? 4
+insert line-invalid-prompt-command-unknown : +20 ? 5
+insert line-invalid-prompt-command-unknown : +21 ? 6
+insert line-invalid-prompt-command-unknown : +22 ? 7
+insert line-invalid-prompt-command-unknown : +23 ? foo_0123456789_0123456789_0123456789
+insert line-invalid-prompt-command : +24 ? /foo_0123456789_0123456789_0123456789_§§
+insert line-bright-red-bold : +25 ?    unknown
+insert line-invalid-prompt-command : +26 ? /bar_0123456789_0123456789_0123456789_§§
+insert line-bright-red-bold : +27 ?    unknown
+insert line-tui-log : +28 ? windows available via /window:§§
+insert line-tui-log : +29 ?   0) :start§§
+insert line-tui-log : +30 ?   1) foo.bar.baz:debug§§
+insert line-tui-log : +31 ?   2) foo.bar.baz:server§§
 
 × history_1
-line 0 on_black,bright_white 20§§-§§-§§ §§
-line 1 on_black,bright_yellow $ §§:§§:§§ isupport cleared
-line 2 on_black,bright_yellow $ §§:§§:§§ isupport:CHANTYPES set to: [#&]
-line 3 on_black,bright_yellow $ §§:§§:§§ isupport:PREFIX set to: [(ov)@+]
-line 4 on_black,bright_yellow $ §§:§§:§§ isupport:USERLEN set to: [10]
-line 5 on_black,bright_yellow $ §§:§§:§§ caps cleared
-line 6 on_black,bright_yellow $ §§:§§:§§ users cleared
-line 7 on_black,bright_yellow $ §§:§§:§§ channels cleared
-line 8 on_black,bright_yellow $ §§:§§:§§ hostname set to: [foo.bar.baz]
-line 9 on_black,bright_yellow $ §§:§§:§§ port set to: [-1]
-line 10 on_black,bright_yellow $ §§:§§:§§ nick_wanted set to: [foo]
-line 11 on_black,bright_yellow $ §§:§§:§§ user_wanted set to: [baz]
-line 12 on_black,bright_yellow $ §§:§§:§§ realname set to: [bar]
-line 13 on_black,bright_yellow $ §§:§§:§§ port set to: [6697]
-line 14 on_black,bright_yellow $ §§:§§:§§ connection_state set to: [connecting]
-line 15 on_black,bright_yellow $ §§:§§:§§ connection_state set to: [connected]
-line 16 on_black,bright_green > §§:§§:§§ CAP LS :302§§
-line 17 on_black,bright_green > §§:§§:§§ USER baz 0 * :bar§§
-line 18 on_black,bright_green > §§:§§:§§ NICK :foo§§
-line 19 on_black,bright_white < §§:§§:§§ PING :?
-line 20 on_black,bright_green > §§:§§:§§ PONG :?
-line 21 on_black,bright_white < §§:§§:§§ PING :9 123456789 123456789 123456789 123456789 123456789 123456789§§
-line 22 on_black,bright_white    123456789 123456789§§
-line 23 on_black,bright_green > §§:§§:§§ PONG :9 123456789 123456789 123456789 123456789 123456789 123456789§§
-line 24 on_black,bright_green    123456789 123456789§§
-line 25 on_black,bright_white < §§:§§:§§ PING :foo
-line 26 on_black,bright_green > §§:§§:§§ PONG :foo
-line 27 on_black,bright_white < §§:§§:§§ PING :bar
-line 28 on_black,bright_green > §§:§§:§§ PONG :bar
-line 29 on_black,bright_white < §§:§§:§§ PING :baz
-line 30 on_black,bright_green > §§:§§:§§ PONG :baz
-line 31 on_black,bright_white < §§:§§:§§ PING :0
-line 32 on_black,bright_green > §§:§§:§§ PONG :0
-line 33 on_black,bright_white < §§:§§:§§ PING :1
-line 34 on_black,bright_green > §§:§§:§§ PONG :1
-line 35 on_black,bright_white < §§:§§:§§ PING :2
-line 36 on_black,bright_green > §§:§§:§§ PONG :2
-line 37 on_black,bright_white < §§:§§:§§ PING :3
-line 38 on_black,bright_green > §§:§§:§§ PONG :3
-line 39 on_black,bright_white < §§:§§:§§ PING :4
-line 40 on_black,bright_green > §§:§§:§§ PONG :4
-line 41 on_black,bright_white < §§:§§:§§ PING :5
-line 42 on_black,bright_green > §§:§§:§§ PONG :5
-line 43 on_black,bright_white < §§:§§:§§ PING :6
-line 44 on_black,bright_green > §§:§§:§§ PONG :6
-line 45 on_black,bright_white < §§:§§:§§ PING :7
-line 46 on_black,bright_green > §§:§§:§§ PONG :7
-line 47 on_black,bright_white < §§:§§:§§ PING :8
-line 48 on_black,bright_green > §§:§§:§§ PONG :8
-line 49 on_black,bright_white < §§:§§:§§ PING :9
-line 50 on_black,bright_green > §§:§§:§§ PONG :9
-line 51 on_black,bright_white < §§:§§:§§ PING :10
-line 52 on_black,bright_green > §§:§§:§§ PONG :10
-line 53 on_black,bright_white < §§:§§:§§ PING :11
-line 54 on_black,bright_green > §§:§§:§§ PONG :11
-line 55 on_black,bright_white < §§:§§:§§ PING :12
-line 56 on_black,bright_green > §§:§§:§§ PONG :12
-line 57 on_black,bright_white < §§:§§:§§ PING :13
-line 58 on_black,bright_green > §§:§§:§§ PONG :13
-line 59 on_black,bright_white < §§:§§:§§ PING :14
-line 60 on_black,bright_green > §§:§§:§§ PONG :14
-line 61 on_black,bright_white < §§:§§:§§ PING :15
-line 62 on_black,bright_green > §§:§§:§§ PONG :15
-line 63 on_black,bright_white < §§:§§:§§ PING :16
-line 64 on_black,bright_green > §§:§§:§§ PONG :16
-line 65 on_black,bright_white < §§:§§:§§ PING :17
-line 66 on_black,bright_green > §§:§§:§§ PONG :17
-line 67 on_black,bright_white < §§:§§:§§ PING :18
-line 68 on_black,bright_green > §§:§§:§§ PONG :18
-line 69 on_black,bright_white < §§:§§:§§ PING :19
-line 70 on_black,bright_green > §§:§§:§§ PONG :19
-line 71 on_black,bright_white < §§:§§:§§ PING :20
-line 72 on_black,bright_green > §§:§§:§§ PONG :20
-line 73 on_black,bright_white < §§:§§:§§ PING :21
-line 74 on_black,bright_green > §§:§§:§§ PONG :21
-line 75 on_black,bright_white < §§:§§:§§ PING :22
-line 76 on_black,bright_green > §§:§§:§§ PONG :22
-line 77 on_black,bright_white < §§:§§:§§ PING :23
-line 78 on_black,bright_green > §§:§§:§§ PONG :23
+insert line-cal : +0
+insert line-server-log : +1 ? isupport cleared
+insert line-server-log : +2 ? isupport:CHANTYPES set to: [#&]
+insert line-server-log : +3 ? isupport:PREFIX set to: [(ov)@+]
+insert line-server-log : +4 ? isupport:USERLEN set to: [10]
+insert line-server-log : +5 ? caps cleared
+insert line-server-log : +6 ? users cleared
+insert line-server-log : +7 ? channels cleared
+insert line-server-log : +8 ? hostname set to: [foo.bar.baz]
+insert line-server-log : +9 ? port set to: [-1]
+insert line-server-log : +10 ? nick_wanted set to: [foo]
+insert line-server-log : +11 ? user_wanted set to: [baz]
+insert line-server-log : +12 ? realname set to: [bar]
+insert line-server-log : +13 ? port set to: [6697]
+insert line-server-log : +14 ? connection_state set to: [connecting]
+insert line-server-log : +15 ? connection_state set to: [connected]
+insert line-client-msg : +16 ? CAP LS :302
+insert line-client-msg : +17 ? USER baz 0 * :bar
+insert line-client-msg : +18 ? NICK :foo
+insert line-ping : +19 ? ?
+insert line-pong : +20 ? ?
+insert line-ping : +21 ? 9 123456789 123456789 123456789 123456789 123456789 123456789§§
+insert line-bright-white : +22 ?    123456789 123456789
+insert line-pong : +23 ? 9 123456789 123456789 123456789 123456789 123456789 123456789§§
+insert line-bright-green : +24 ?    123456789 123456789
+insert line-ping : +25 ? foo
+insert line-pong : +26 ? foo
+insert line-ping : +27 ? bar
+insert line-pong : +28 ? bar
+insert line-ping : +29 ? baz
+insert line-pong : +30 ? baz
+insert line-ping : +31 ? 0
+insert line-pong : +32 ? 0
+insert line-ping : +33 ? 1
+insert line-pong : +34 ? 1
+insert line-ping : +35 ? 2
+insert line-pong : +36 ? 2
+insert line-ping : +37 ? 3
+insert line-pong : +38 ? 3
+insert line-ping : +39 ? 4
+insert line-pong : +40 ? 4
+insert line-ping : +41 ? 5
+insert line-pong : +42 ? 5
+insert line-ping : +43 ? 6
+insert line-pong : +44 ? 6
+insert line-ping : +45 ? 7
+insert line-pong : +46 ? 7
+insert line-ping : +47 ? 8
+insert line-pong : +48 ? 8
+insert line-ping : +49 ? 9
+insert line-pong : +50 ? 9
+insert line-ping : +51 ? 10
+insert line-pong : +52 ? 10
+insert line-ping : +53 ? 11
+insert line-pong : +54 ? 11
+insert line-ping : +55 ? 12
+insert line-pong : +56 ? 12
+insert line-ping : +57 ? 13
+insert line-pong : +58 ? 13
+insert line-ping : +59 ? 14
+insert line-pong : +60 ? 14
+insert line-ping : +61 ? 15
+insert line-pong : +62 ? 15
+insert line-ping : +63 ? 16
+insert line-pong : +64 ? 16
+insert line-ping : +65 ? 17
+insert line-pong : +66 ? 17
+insert line-ping : +67 ? 18
+insert line-pong : +68 ? 18
+insert line-ping : +69 ? 19
+insert line-pong : +70 ? 19
+insert line-ping : +71 ? 20
+insert line-pong : +72 ? 20
+insert line-ping : +73 ? 21
+insert line-pong : +74 ? 21
+insert line-ping : +75 ? 22
+insert line-pong : +76 ? 22
+insert line-ping : +77 ? 23
+insert line-pong : +78 ? 23
 
 ×
 
 insert lines-empty
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # nothing happening on empty command input
 > 
 insert lines-empty
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scrolling on empty history does nothing
 > /window.history.scroll up
 insert lines-empty
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 > /window.history.scroll down
 insert lines-empty
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # non-empty command input starts log at bottom, with date above it
 > foo
 log 0 # invalid prompt command: not prefixed by /
 insert lines-empty :20
 insert history_0 :2 +20
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scrolling on history merely 2 lines long won't do anything either
 > /window.history.scroll up
 insert lines-empty :20
 insert history_0 :2 +20
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 > /window.history.scroll down
 insert lines-empty :20
 insert history_0 :2 +20
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # further inputs grow log upwards
 > /foo
 log 0 # invalid prompt command: /foo unknown
 insert lines-empty :19
 insert history_0 :3 +19
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scrolling up does something on history 3 lines long
 > /window.history.scroll up
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-2
-insert status-[0]-prompt
+insert line-scrolldown : +21 XXXXXX [2] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scrolling down on 3-lines history
 > /window.history.scroll down
 insert lines-empty :19
 insert history_0 :3 +19
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check history growing below up-scroll
 > /window.history.scroll up
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-2
-insert status-[0]-prompt
+insert line-scrolldown : +21 XXXXXX [2] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 > /help
 log 0 # commands available in this window:
 log 0 #   /connect HOST_PORT [NICKNAME_PW] [REALNAME_USERNAME]
@@ -322,33 +267,33 @@ log 0 #   /window.prompt.move_cursor DIRECTION
 log 0 #   /window.prompt.scroll DIRECTION
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-14
-insert status-[0:12]-prompt
+insert line-scrolldown : +21 XXXXXX [14] v
+insert lines-status-prompt-start : +22 X123456789X123456789X ============([(0:12)]
 
 # check scroll-down on newer history longer than half a screen width does not fully land at bottom
 > /window.history.scroll down
 insert lines-empty :9
 insert history_0 :12 +9
-insert scrolldown-3
-insert status-[0:3]-prompt
+insert line-scrolldown : +21 XXXXXX [3] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:3)]
 
 # check previous scroll-down not hitting bottom be fully reversible
 > /window.history.scroll up
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-14
-insert status-[0:3]-prompt
+insert line-scrolldown : +21 XXXXXX [14] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:3)]
 > /window.history.scroll down
 insert lines-empty :9
 insert history_0 :12 +9
-insert scrolldown-3
-insert status-[0:3]-prompt
+insert line-scrolldown : +21 XXXXXX [3] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:3)]
 
 # scroll to bottom, check history still growing up even beyond upper fold
 > /window.history.scroll down
 insert lines-empty :7
 insert history_0 :15 +7
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 > /0
 log 0 # invalid prompt command: /0 unknown
 > /1
@@ -366,19 +311,19 @@ log 0 # invalid prompt command: /6 unknown
 > /7
 log 0 # invalid prompt command: /7 unknown
 insert history_0 1:23 +0
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scroll-down even with long history does nothing
 > /window.history.scroll down
 insert history_0 1:23 +0
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # quick look one scroll up to check single-scroll increase of below-scroll count (when up-scroll not limited, and all lines un-wrapped)
 > /window.history.scroll up
 insert lines-empty :9
 insert history_0 :12 +9
-insert scrolldown-11
-insert status-[0]-prompt
+insert line-scrolldown : +21 XXXXXX [11] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check wrapping
 > /window.history.scroll down
@@ -387,55 +332,55 @@ log 0 # invalid prompt command: /foo_0123456789_0123456789_0123456789 unknown
 > /foo_0123456789_0123456789_0123456789_
 log 0 # invalid prompt command: /foo_0123456789_0123456789_0123456789_ unknown
 insert history_0 4:26 +0
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scroll-up over wrapped moves up less history lines than screen lines
 > /window.history.scroll up
 insert lines-empty :6
 insert history_0 :15 +6
-insert scrolldown-10
-insert status-[0]-prompt
+insert line-scrolldown : +21 XXXXXX [10] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check scroll-down fully reversible even if over wrapped
 > /window.history.scroll down
 insert history_0 4:26 +0
-insert status-[0]-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 > /window.history.scroll up
 insert lines-empty :6
 insert history_0 :15 +6
-insert scrolldown-10
-insert status-[0]-prompt
+insert line-scrolldown : +21 XXXXXX [10] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =================([0]
 
 # check wrapped input only increases below-scroll count by one
 > /bar_0123456789_0123456789_0123456789_
 log 0 # invalid prompt command: /bar_0123456789_0123456789_0123456789_ unknown
 insert lines-empty :6
 insert history_0 :15 +6
-insert scrolldown-11
-insert status-[0:1]-prompt
+insert line-scrolldown : +21 XXXXXX [11] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:1)]
 
 # check scroll-down over wrapped will snap down to bottom of wrapped
 > /window.history.scroll down
 insert history_0 5:26 +0
-insert scrolldown-1
-insert status-[0:1]-prompt
+insert line-scrolldown : +21 XXXXXX [1] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:1)]
 
 # # check scrolls-up over longer history until top
 > /window.history.scroll up
 insert lines-empty :6
 insert history_0 :15 +6
-insert scrolldown-11
-insert status-[0:1]-prompt
+insert line-scrolldown : +21 XXXXXX [11] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:1)]
 > /window.history.scroll up
 insert lines-empty :17
 insert history_0 :3 +17
-insert scrolldown-22
-insert status-[0:1]-prompt
+insert line-scrolldown : +21 XXXXXX [22] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:1)]
 > /window.history.scroll up
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-25
-insert status-[0:1]-prompt
+insert line-scrolldown : +21 XXXXXX [25] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =============([(0:1)]
 
 # check that triggering creation of new window with new lines adds it to status, with unread-lines count
 > /connect foo.bar.baz foo bar:baz
@@ -466,62 +411,62 @@ log 1 > USER baz 0 * :bar
 log 1 > NICK :foo
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-25
-insert status-[0:1]-1:19-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [25] v
+insert lines-status-prompt-start : +22 X123456789X123456789X ([(0:1)] (1:19) (2:7)
 
 # check switch to other window, updates to status line (movement of brackets, clearing of own unread-lines count)
 > /window 1
 insert lines-empty :3
 insert history_1 :19 +3
-insert status-0:1-[1]-(2:7)-prompt
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====((0:1) [1] (2:7)
 
 # check switch-back to window 0, retaining clearing of window 1's unread-lines count
 > /window 0
 insert lines-empty :20
 insert history_0 :1 +20
-insert scrolldown-25
-insert status-[0:1]-1-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [25] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([(0:1)] 1 (2:7)
 
 # check that on full scroll-down, we now have a bookmark above the newest lines not previously scrolled into
 > /window.history.scroll down
 insert lines-empty :9
 insert history_0 :12 +9
-insert scrolldown-14
-insert status-[0:1]-1-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [14] v
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([(0:1)] 1 (2:7)
 > /window.history.scroll down
 insert history_0 2:23 +0
-insert scrolldown-3
-insert status-[0:1]-1-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [3] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([(0:1)] 1 (2:7)
 > /window.history.scroll down
 insert history_0 7:26 +0
-insert bookmark : +19
+insert line-bookmark : +19
 insert history_0 26:28 +20
-insert status-[0]-1-(2:7)-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =========([0] 1 (2:7)
 
 # check that scrolling non-bottom bookmark out of sight, then scrolling it back into view again does not by itself move its position in the log history
 > /window.history.scroll up
 insert lines-empty :3
 insert history_0 :18 +3
-insert scrolldown-8
-insert status-[0]-1-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [8] vv
+insert lines-status-prompt-start : +22 X123456789X123456789X =========([0] 1 (2:7)
 > /window.history.scroll down
 insert history_0 7:26 +0
-insert bookmark : +19
+insert line-bookmark : +19
 insert history_0 26:28 +20
-insert status-[0]-1-(2:7)-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =========([0] 1 (2:7)
 
 # check that second switch to new window, previously left on bottom of history, establishes bookmark at bottom of log
 > /window 1
 insert lines-empty :2
 insert history_1 :19 +2
-insert bookmark : +21
-insert status-0-[1]-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 
 # check second switch-back places bookmark at bottom there too, since the newest lines previously succeeding it have now been read by us
 > /window 0
 insert history_0 7:28 +0
-insert bookmark : +21
-insert status-[0]-1-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X =========([0] 1 (2:7)
 
 # check new lines push bookmark up
 > /list
@@ -530,9 +475,9 @@ log 0 #   0) :start
 log 0 #   1) foo.bar.baz:debug
 log 0 #   2) foo.bar.baz:server
 insert history_0 11:28 +0
-insert bookmark : +17
+insert line-bookmark : +17
 insert history_0 28:32 +18
-insert status-[0]-1-(2:7)-prompt
+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 :?
@@ -540,16 +485,16 @@ log 1 > PONG :?
 loggedservermsg 0 1 < 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 bookmark : +17
+insert line-bookmark : +17
 insert history_0 28:32 +18
-insert status-[0]-1:4-(2:7)-prompt
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:4) (2:7)
 
 # check that switching to window with new lines, but left scroll-to-bottom, keeps the scroll-to-bottom, keeps bookmark after last line previously seen there
 > /window 1
 insert history_1 4:19 +0
-insert bookmark : +15
+insert line-bookmark : +15
 insert history_1 19:25 +16
-insert status-0-[1]-(2:7)-prompt
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 
 ### # check that growth below scroll does not by itself re-position bookmark in history
 > /window.history.scroll up
@@ -557,102 +502,102 @@ loggedservermsg 0 1 < PING :foo
 log 1 > PONG :foo
 insert lines-empty :6
 insert history_1 0:15 +6
-insert scrolldown-10
-insert status-0-[1:2]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [10] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 > /window.history.scroll down
 insert history_1 5:19 +0
-insert bookmark : +14
+insert line-bookmark : +14
 insert history_1 19:25 +15
-insert scrolldown-2
-insert status-0-[1:2]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [2] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 
 # check that with new lines left unread, switch away and back into window moves bookmark below newest read line, counts unread lines in status
 > /window 0
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:2-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:2) (2:7)
 > /window 1
 insert history_1 5:25 +0
-insert bookmark : +20
-insert scrolldown-2
-insert status-0-[1:2]-(2:7)-prompt
+insert line-bookmark : +20
+insert line-scrolldown : +21 XXXXXX [2] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 
 # 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
 log 1 > PONG :bar
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:4-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:4) (2:7)
 > /window 1
 insert history_1 5:25 +0
-insert bookmark : +20
-insert scrolldown-4
-insert status-0-[1:4]-(2:7)-prompt
+insert line-bookmark : +20
+insert line-scrolldown : +21 XXXXXX [4] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:4)] (2:7)
 
 # check same applies when leaving affected window with bookmark out-of-sight
 > /window.history.scroll up
 insert lines-empty :6
 insert history_1 :15 +6
-insert scrolldown-12
-insert status-0-[1:4]-(2:7)-prompt
+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
 log 1 > PONG :baz
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:6-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:6) (2:7)
 > /window 1
 insert lines-empty :6
 insert history_1 :15 +6
-insert scrolldown-14
-insert status-0-[1:6]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [14] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:6)] (2:7)
 > /window.history.scroll down
 insert history_1 5:25 +0
-insert bookmark : +20
-insert scrolldown-6
-insert status-0-[1:6]-(2:7)-prompt
+insert line-bookmark : +20
+insert line-scrolldown : +21 XXXXXX [6] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:6)] (2:7)
 > /window.history.scroll down
 insert history_1 10:25 +0
-insert bookmark : +15
+insert line-bookmark : +15
 insert history_1 25:31 +16
-insert status-0-[1]-(2:7)-prompt
+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
 log 1 > PONG :0
 insert history_1 12:25 +0
-insert bookmark : +13
+insert line-bookmark : +13
 insert history_1 25:33 +14
-insert status-0-[1]-(2:7)-prompt
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 > /window.history.scroll up
 insert history_1 2:23 +0
-insert scrolldown-9
-insert status-0-[1]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [9] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 > /window.history.scroll up
 insert lines-empty :10
 insert history_1 1:12 +10
-insert scrolldown-19
-insert status-0-[1]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [19] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 > /window.history.scroll up
 insert lines-empty :20
 insert history_1 1:2 +20
-insert scrolldown-29
-insert status-0-[1]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [29] v
+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
 log 1 > PONG :0
 insert lines-empty :20
 insert history_1 3:4 +20
-insert scrolldown-29
-insert status-0-[1:2]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [29] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 
 # check unread-lines count potentially growing above max log depth if in other window
 > /window 0
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:2-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X =====([0] (1:2) (2:7)
 loggedservermsg 0 1 < PING :1
 log 1 > PONG :1
 loggedservermsg 0 1 < PING :2
@@ -684,60 +629,60 @@ log 1 > PONG :14
 loggedservermsg 0 1 < PING :15
 log 1 > PONG :15
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:32-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X ====([0] (1:32) (2:7)
 
 # check switching into window scrolled-top with more unread lines than max log depth shrinks former to latter, and scrolling down no bookmark is to be found
 > /window 1
 insert lines-empty :20
 insert history_1 33:34 +20
-insert scrolldown-29
-insert status-0-[1:29]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [29] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X ====(0 [(1:29)] (2:7)
 > /window.history.scroll down
 insert lines-empty :9
 insert history_1 33:45 +9
-insert scrolldown-18
-insert status-0-[1:18]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [18] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X ====(0 [(1:18)] (2:7)
 > /window.history.scroll down
 insert history_1 35:56 +0
-insert scrolldown-7
-insert status-0-[1:7]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [7] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:7)] (2:7)
 > /window.history.scroll down
 insert history_1 41:61 +0
-insert status-0-[1]-(2:7)-prompt
+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
 log 1 > PONG :16
 insert history_1 43:63 +0
-insert status-0-[1]-(2:7)-prompt
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 
 # … as well as if further growth happens below scroll 
 > /window.history.scroll up
 insert lines-empty :2
 insert history_1 35:54 +2
-insert scrolldown-11
-insert status-0-[1]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [11] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 loggedservermsg 0 1 < PING :17
 log 1 > PONG :17
 insert lines-empty :4
 insert history_1 37:54 +4
-insert scrolldown-13
-insert status-0-[1:2]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [13] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 > /window.history.scroll down 
 insert history_1 44:65 +0
-insert scrolldown-2
-insert status-0-[1:2]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [2] vv
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =====(0 [(1:2)] (2:7)
 > /window.history.scroll down 
 insert history_1 45:67 +0
-insert status-0-[1]-(2:7)-prompt
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 
 # check unread-lines status not growing beyond max log if within active window, and …
 > /window.history.scroll up
 insert lines-empty :2
 insert history_1 37:54 +2
-insert scrolldown-11
-insert status-0-[1]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [11] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X =========(0 [1] (2:7)
 loggedservermsg 0 1 < PING :18
 log 1 > PONG :18
 loggedservermsg 0 1 < PING :19
@@ -770,24 +715,24 @@ loggedservermsg 0 1 < PING :32
 log 1 > PONG :32
 insert lines-empty :20
 insert history_1 67:68 +20
-insert scrolldown-29
-insert status-0-[1:29]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [29] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X ====(0 [(1:29)] (2:7)
 
 # … setting bookmark visible after switching back-and-forth
 > /window 0
 insert history_0 11:32 +0
-insert bookmark : +21
-insert status-[0]-1:29-(2:7)-prompt
+insert line-bookmark : +21
+insert lines-status-prompt-start : +22 X123456789X123456789X ====([0] (1:29) (2:7)
 > /window 1
 insert lines-empty :19
 insert history_1 67:68 +19
-insert bookmark : +20
-insert scrolldown-29
-insert status-0-[1:29]-(2:7)-prompt
+insert line-bookmark : +20
+insert line-scrolldown : +21 XXXXXX [29] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X ====(0 [(1:29)] (2:7)
 > /window.history.scroll down
 insert lines-empty :8
 insert history_1 67:68 +8
-insert bookmark : +9
+insert line-bookmark : +9
 insert history_1 68:79 +10
-insert scrolldown-18
-insert status-0-[1:18]-(2:7)-prompt
+insert line-scrolldown : +21 XXXXXX [18] v
+insert lines-status-prompt-foobarbaz : +22 X123456789X123456789X ====(0 [(1:18)] (2:7)