diff -uNr a/yrc/manifest b/yrc/manifest --- a/yrc/manifest e164eeb41b3d8210753a65acb4645e36b8bef7bb6cb87626abfb491b4d8ef31264f885740caaacc770fd2bf5e659132e056323ae1ef0fdba2566929912728f04 +++ b/yrc/manifest 5ad53d0721b60a070f835e28a56823c617ecf4b7d14878cad6f391ef3410b9b1cbd3a3d3b4133f1878ee7efcab58608f80f24a07112ee81ab53daee03fddae55 @@ -10,3 +10,4 @@ 768778 yrc_reindent_docs jfw Reindent spaces to tabs in documentation. (In README.txt, indentation levels are reduced across the board.) 769932 yrc_minor_char_refactors jfw Use backspace character code from yterm rather than showing it in long form. Replace char_range() with simple character classifier functions (consistent with the existing ones and potentially faster than string membership tests). Add citations for some strange IRC character classifications (which came up when looking into how to delimit completion prefixes). 769934 yrc_completion jfw Implement tab completion for nicks, channels and slash commands. Relatedly: factor out the now common case of inserting multiple characters into the prompt at once, as insert_multi; correct rfind_word_start and find_word_end to always return a valid cursor position (empty returns previously happened to work due to obscure details of None handling); turn the leading slash into a proper part of slash command names, facilitating completion and better distinguishing them from keyboard commands. (Slash commands without parameters could in theory still be given key mappings, but the normal keyboard editing & scrolling commands make little sense to type at the prompt and are no longer recognized there.) +769938 yrc_net_level_commands jfw Implement /close-net and /reconnect commands, and straighten out which commands can take a part/quit message. A reliable QUIT message *could* be implemented for /disconnect and /close-net (unlike for /quit), so make space to add it there by dropping the optional network name argument from /disconnect, which I found to be more confusing than helpful anyway. diff -uNr a/yrc/manual.txt b/yrc/manual.txt --- a/yrc/manual.txt cd116294c22e74fc7f9b4e66afc943f4b853881c8ef9f66f4d45d5323bbac4171953d0591cb336b1b91ec8a18e38de3f8849b38373ca8570a21a470d333260ed +++ b/yrc/manual.txt a881ee36fcf2116e6c2be18c655c7a5fb6b74fcb1288bff3ea5e7ee8c225527d889e05b09e3a1a493a7ecb86d42ee0d85214226aa38759ebb7799a89f9950b04 @@ -101,9 +101,9 @@ Connect to NETWORK, either preconfigured or with the given parameters. - [d]isconnect [NETWORK] + [d]isconnect -Disconnect from NETWORK or the current network, or cancel a reconnection attempt. +Disconnect from the current network, or cancel a reconnection attempt. [j]oin CHANNEL [KEY] @@ -141,10 +141,14 @@ Leave the current channel, keeping its window open. - [q]uit [QUIT_MESSAGE] + [q]uit Disconnect from all networks and quit yrc. + [r]econnect + +Reconnect to the current network, as if from a ping timeout, perhaps to switch to another server in rotation. Unlike disconnect followed by connect, network configuration is not reloaded, the runtime nick setting is retained, and previous channels are rejoined. + [s]end COMMAND Send a raw IRC command to the server for the current network. @@ -165,11 +169,11 @@ Request cached information for a disconnected user on the current network. - [x] close + [x] close [PART_MESSAGE] -Close the current window, parting with no message if it is a channel. +Close the current window, parting if it is a channel. - [xn] close-net (TODO) + [xn] close-net Disconnect and close all windows for the current network. @@ -408,7 +412,7 @@ High-priority missing features: - - Finish mode/op and close-net commands + - Finish mode/op commands - Scrolling in window list if it exceeds available screen rows - More accurate derivation of message length limit to reduce overly-conservative wrapping diff -uNr a/yrc/yrc.py b/yrc/yrc.py --- a/yrc/yrc.py cc6bf18dfc43af4d1bfb7ec3accaa2148283160120701d87e8cfd14a3de088bb4748c91190b8b250c846bf80de0ac65f9c50bb07891b2f25787c293ed76ec4e3 +++ b/yrc/yrc.py 8c8be23b92366ffdfe83aa47802ff738e43be93a40495265e1303eecd35fb84cdcd1b3ba8796da2264d4ea82dd8257d02513b8eb6f1794a85d1024efa106292b @@ -10,7 +10,7 @@ KILL_RING_SIZE = 8 HISTORY_RING_SIZE = 1024 DEFAULT_PORT = 6667 -RECONN_DELAY_MIN = 4 # seconds +RECONN_DELAY_MIN = 1 # second(s) RECONN_DELAY_MAX = 256 PING_INTERVAL = 120 PING_TIMEOUT = 240 @@ -208,6 +208,7 @@ '/nam': '/names', '/p': '/part', '/q': '/quit', + '/r': '/reconnect', '/s': '/send', '/t': '/topic', '/st': '/set-topic', @@ -1562,18 +1563,11 @@ conn_start(new_conn(net, addrs, nick, pw)) -@command('/disconnect', 0, 1) -def disconnect_cmd(net=None): - if net is None: - c = buf_conn(cur_buf) - net = conn_network(c) - else: - try: - c = network_conns[net] - except KeyError: - raise CommandError('no connection for network %s' % net) - del network_conns[net] - conn_info(c, 'disconnected') +@command('/disconnect') +def disconnect_cmd(): + # In theory we could send a QUIT message, but it would require scheduling to get flushed before closing the socket. It's also dubious that such a delay should even be allowed, because we don't want to hear anything further from the server past this point (though that could perhaps be achieved by filtering elsewhere). Finally, since /quit can't do it in any case and is probably the more common command, it doesn't really seem worth it. + c = buf_conn(cur_buf) + del network_conns[conn_network(c)] conn_close(c) @command('/join', 1, 2) @@ -1637,11 +1631,14 @@ raise CommandError('part: this window not a channel') conn_send(buf_registered_conn(cur_buf), 'PART', [chan, msg]) -@command('/quit', extended_arg=True) -def quit_cmd(*msg): +@command('/quit') +def quit_cmd(): + # Can't reliably send QUIT messages: writing is async because it can block, but the user told us to quit so we're not going to wait on the network. schedule_quit() - for c in open_conns.itervalues(): - conn_send(c, 'QUIT', msg) + +@command('/reconnect') +def reconnect_cmd(): + conn_close(buf_conn(cur_buf)) @command('/send', extended_arg=True) def send_cmd(line): @@ -1673,8 +1670,8 @@ def whowas_cmd(nick): conn_send(buf_registered_conn(cur_buf), 'WHOWAS', [nick]) -@command('/close') -def close_cmd(): +@command('/close', extended_arg=True) +def close_cmd(msg=''): parent = buf_parent(cur_buf) if parent is None: raise CommandError( @@ -1686,13 +1683,24 @@ pass else: if venue in conn_channels(c): - conn_send(c, 'PART', [venue, '']) + conn_send(c, 'PART', [venue, msg]) del conn_channels(c)[venue] close_buf(cur_buf) @command('/close-net') def close_net_cmd(): - raise CommandError('stub') # TODO + disconnect_cmd() + # Get the top (network) level window + parent = buf_parent(cur_buf) + if parent is None: + # Already on it + parent = cur_buf + # Close it + close_buf(parent) + # Close the children (chats and PMs) + for b in buffers[:]: # Copy because we mutate original list as we go + if buf_parent(b) is parent: + close_buf(b) def place_cursor(): if buflist_flag(): @@ -1995,7 +2003,7 @@ if conn_network(c) in network_conns: delay = conn_reconn_delay(c) conn_run_in(c, delay, conn_start, True) - conn_info(c, 'reconnecting in %d seconds' % delay) + conn_info(c, 'reconnecting in %d s' % delay) def conn_handle_data(c, data): conn_rdbuf_add(c, data)