The yrc manual Version 95 Kelvin Jacob Welsh Table of Contents 1 About yrc 2 Display 3 Commands 3.1 Slash commands 3.2 Keyboard commands 3.2.1 Anywhere 3.2.2 In the window list 3.2.3 At the prompt 3.2.4 In the scrollback window 4 Configuration 4.1 Keys 4.2 Logging 4.3 Example 5 Roadmap 6 News and contact Footnotes 1. About yrc yrc is a text-based, screen-oriented Internet Relay Chat (IRC) client providing a vital dose of simplicity in a computing world drowning in complexity. There are certain things that just shouldn't have bugs, and in the author's opinion, chat programs are among them. Simple does not necessarily mean "user-friendly" in the sense that you can expect to operate it without reading this manual. It does mean the literate operator should be able to read and comprehend the manual in an hour or two, and on this basis to fully grasp the workings of the program with a little practice. For yrc to achieve its goals, the following decisions were made: 1. High-level language implementation. In a network-exposed, not performance-critical application, there's just no excuse for the possibility of invoking Undefined Behavior and the ensuing vulnerabilities. 2. Simple configuration mechanism employing the filesystem as a hierarchical key-value database; no structured format to parse. [1] 3. Support exclusively VT100-compatible terminals on Unix-like systems. 4. No dependencies besides POSIX. [2] 5. No superfluous features such as mIRC colors, DCC or CTCP. [3] 6. No Unicode or any other flavor of hieroglyphs. Control and 8-bit characters in any IRC string are sanitized on display, both to protect the terminal and show the operator exactly what he is receiving. [4] 7. No SSL/TLS/TLS_1.3/whatever-they're-calling-it-today. [5] It does support several niceties: 1. Multiple message windows (separated channels/conversations) 2. Maintenance of connections to multiple networks, defined either by configuration or on the fly 3. Round-robin server balancing independent of DNS 4. Unlimited scrollback [6] 5. Basic authentication (the PASS command) 6. Sending raw commands to the IRC server for unsupported features 7. Communication of internal state to the operator: unread messages, connection state 8. Chat logging It is written in Python 2.6 (though this is an implementation detail and subject to change). Some of its more reusable terminal interface code is included as a separate "yterm" module. The yrc+yterm code weighs in around 2390 raw lines, compressing to 19KB. yrc is written, published and maintained by JWRD Computing ( http://jwrd.net/ ). 2. Display The yrc display is designed to maximize information and context available on a single screen, because eyes move faster than fingers. It has five parts: Title bar: shows a description of the current window, or the channel topic. Window list: an index of open windows (see below). Scrollback window: shows message history for a particular channel or private conversation, or server messages for a network, or general messages. Status bar: typically, shows the current nickname, network, and message target. Prompt: messages and commands are typed here. The window list is kept in alphabetical order, grouped by network, after the general messages window "yrc". An asterisk (*) in the first column indicates the currently selected window and a hyphen (-) the previous. Unread messages are indicated by a +N after the window name, where N is the number unread. A network's connection state is indicated by a symbol in front of its name, as follows: Blank: Not connected Tilde (~): Connection down: awaiting TCP handshake completion, or connection lost and waiting to reconnect Hyphen (-): TCP connection established but not registered to the server Equals (=): Fully registered; clear to send messages 3. Commands yrc is controlled using _slash commands_ and _keyboard commands_. Slash commands are entered at the prompt by starting the line with the forward "/" character. Most can be given as abbreviations, as indicated below. Some take one or more space-delimited arguments. To send a line starting with a slash as a normal message, use two slashes. Keyboard commands are invoked by typing special keys or key combinations. For interactive use, the phrases "current network" or "current channel" mean the network or channel of the currently selected window. For scripts (not yet implemented), they mean the network or channel under which the script is configured. 3.1. Slash commands [c]onnect NETWORK [HOST[:PORT] [NICK [PASS]]] Connect to NETWORK, either preconfigured or with the given parameters. [d]isconnect Disconnect from the current network, or cancel a reconnection attempt. [j]oin CHANNEL [KEY] Join a channel on the current network. [k]ick USER [MESSAGE] Kick a user from the current channel. [l]ist [CHANNEL] Request a list of channels and topics, or the status of a given channel, on the current network. me MESSAGE Send MESSAGE as a CTCP ACTION (rendered by many clients in an alternate style showing the nickname as the start of a sentence). [m]ode MODE {[CHANNEL] | NICK [CHANNEL]} [TODO; uncertain...] Set a mode on CHANNEL or the current channel, or a user mode on NICK in CHANNEL or the current channel. msg {CHANNEL | NICK} [MESSAGE] Switch to the window for CHANNEL or NICK on the current network, creating one if needed, and send the given MESSAGE, if any. (This does not join a channel; messages to an unjoined channel might be rejected by the server.) [na]mes [CHANNEL] Request the list of names in the given channel, or all visible channels and users on the current network. [n]ick NICK Temporarily change nickname on the current network (persists across reconnections but not new connections). [p]art [PART_MESSAGE] Leave the current channel, keeping its window open. [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. [st] set-topic TOPIC Set the topic for the current channel to TOPIC. [t]opic [CHANNEL] Get the topic for the current channel or the given channel on the current network. [w]hois NICK Request information on a user on the current network. [ww] whowas NICK Request cached information for a disconnected user on the current network. [x] close [PART_MESSAGE] Close the current window, parting if it is a channel. [xn] close-net Disconnect and close all windows for the current network. 3.2. Keyboard commands In the Emacs tradition, C- means to hold Ctrl, and M- means to hold Alt (Meta). Some commands are multi-key sequences beginning with C-x. For these, you can either continue holding Ctrl or not. That is, C-x n is equivalent to C-x C-n. If necessary, an Alt combination can be emulated by pressing (not holding) Esc followed by the letter. Key sequences in progress are indicated in the status bar and can be cancelled with C-g. Each keyboard command has an associated name (used internally for key mapping and perhaps a future scripting feature). The mapping of some keys to commands depends on which part of the interface is focused. Most commands have multiple keybindings, providing a choice of Emacs, vi, or dedicated key styles. To become a more productive Unix user, it can't hurt to learn them all! 3.2.1. Anywhere C-x n: buflist-switch-next Switches to the next scrollback window in the list. C-x p: buflist-switch-prev Switches to the previous scrollback window in the list. C-x l: buflist-last-selected Switches to the previously active scrollback window. C-x w: buflist-enter Moves focus to the window list (see 3.2.2). C-l: redraw Performs a full redraw of the screen, e.g. in case of corruption from the output of another program. 3.2.2. In the window list C-n, j, Down: buflist-next Moves the cursor to the next entry in the window list. C-p, k, Up: buflist-prev Moves the cursor to the previous entry in the window list. h, Left: buflist-shrink Reduces window list width. l, Right: buflist-grow Increases window list width. M-<, g, Home: buflist-top Moves the cursor to the top of the window list. M->, G, End: buflist-bottom Moves the cursor to the bottom of the window list. Return (C-m): buflist-submit Activates the selected scrollback window and returns focus to where it was. 3.2.3. At the prompt Return (C-m): prompt-submit Submits the message or command given at the prompt. Ins: prompt-exit Moves focus to the scrollback window (see 3.2.4). C-b, Left: prompt-back Moves the cursor backward by one character. C-f, Right: prompt-forward Moves the cursor forward by one character. C-a, Home: prompt-start Moves the cursor to the start of the line. C-e, End: prompt-end Moves the cursor to the end of the line. M-b, prompt-back-word Moves the cursor to the start of the current word, or preceeding word if not currently in one. M-f, prompt-forward-word Moves the cursor past the end of the current word, or following word if not currently in one. C-p, Up: history-prev Recalls a previous line from input history. (History size is currently fixed at 1024 most recent entries.) C-n, Down: history-next Recalls a subsequent line from input history, discarding any unsubmitted edits to a previous line. Backspace (C-h, C-?): prompt-backspace Deletes backward by one character. C-d, Del: prompt-delete Deletes forward by one character. Tab (C-i): prompt-complete Completes word at cursor. Possible completions are drawn from slash commands, currently joined channel names, and nicknames present in the current channel. When the prefix is ambiguous, completes up to the longest common prefix of the candidates (i.e. goes as far as it can based on what was given). C-u: kill-start Deletes text from start of line to cursor, saving it to the kill ring. (Kill ring size is currently fixed at 8 entries.) C-k: kill-end Deletes text from cursor to end of line, saving it to the kill ring. M-Backspace: kill-back-word Deletes text from cursor to start of current or preceeding word, saving it to the kill ring. Multiple kills in a row accumulate into a single entry, allowing the span to be pasted as a whole. M-d: kill-forward-word Deletes text from cursor to end of current or following word, saving it to the kill ring. C-y: yank Inserts ("yanks" or "pastes") the most recent kill ring entry at cursor position. M-y: yank-next Following a yank, replaces the just-inserted text with the next older entry in the kill ring. C-v, PgDn: scroll-down-page M-v, PgUp: scroll-up-page Scrolls the active scrollback window. M-<: scroll-top M->: scroll-bottom Scrolls the active scrollback window to the top or bottom. 3.2.4. In the scrollback window If the window is scrolled to the bottom (the last available message is fully visible), it will autoscroll as new messages arrive. i, Ins: prompt-enter Moves focus to the prompt (see 3.2.3). C-v, C-f, f, PgDn, Space: scroll-down-page M-v, C-b, b, PgUp: scroll-up-page Scrolls the window down or up by a page. C-n, j, Down: scroll-down-line C-p, k, Up: scroll-up-line Scrolls the window down or up by one wrapped line. M-<, g, Home: scroll-top M->, G, End: scroll-bottom Scrolls to the top or bottom. 4. Configuration As mentioned above, yrc is configured using the filesystem as a key-value store. The config tree is rooted at ~/.yrc (the hidden directory ".yrc" under your home directory), known as the yrc home. Each config key is represented by a text file; trailing linefeeds are stripped. Under the yrc home may be a "nets" subdirectory. IRC networks are defined by creating further subdirectories under "nets" with names of your choice; these names are used for NETWORK in the yrc commands. 4.1. Keys The following keys may be defined at top level (directly in the yrc home) or per network, with network level taking precedence. addrs -- one or more server addresses (required) nick -- initial IRC nickname (required) pass -- plain-text password to send on connect Addresses are specified one per line as either hostname or IPv4 address optionally followed by ":" and port number. Lines starting with the "#" character are ignored. Per common practice, the default port is 6667. On initial connection to a network, a server is selected at random; subsequent reconnections by the same process rotate sequentially through the list. 4.2. Logging A "logs" tree is created automatically under the yrc home with subdirectories for each network. Messages associated with chats are appended to log files under these, named by VENUE.log where VENUE is the channel name or correspondent nick, casefolded and %-encoded for problematic characters. [7] To suppress logging for a particular entity, you could symlink its log file to /dev/null. yrc behaves as if each log file is opened fresh on each write, in the sense that deleting, truncating, renaming or linking log files works immediately and as expected. [8] yrc attempts to write each message with a single system call, so concurrent processes should be safe, though not recommended. The log format, designed for a degree of human and machine readability, is one message per line with the following single-space-delimited fields: timestamp -- decimal integer, centiseconds since the epoch type -- mostly matching the IRC protocol but with some variation; consult the "message" variant type in yrc.py for details sender -- quoted in for aesthetics content -- running to end of line Note that unlike in the UI, message content is not escaped; the only characters excluded by protocol are ASCII NUL, CR and LF. Thus printing a log directly to terminal (as opposed to using an editor or "less") can cause unexpected and possibly dangerous behavior. 4.3. Example An example tree, including some planned keys not yet implemented: ~/.yrc |-- nets | |-- net1 | | |-- auto | | |-- addrs | | |-- nick | | |-- pass | | |-- chans | | | `-- #somechan | | | |-- auto | | | `-- key | | `-- contacts | | `-- buddy | `-- net2 | `-- addrs |-- nick |-- realname |-- user `-- logs |-- net1 | |-- buddy.log | `-- #channel.log `-- net2 `-- 1337%2Fhax0r%0A.log 5. Roadmap High-priority missing features: - 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 Nice to have: - Indication of nick mentions (ring bell + bold the window name?) - Formatting for displayed messages (e.g. bold sender, highlight own nick) - Filtering of inbound PMs (/ignore or similar) - Filtering of join, part etc. in rendered scrollback - More efficient navigation of window list - Search in scrollback - Nickname fallback - Online /help command - Auto-connect/join or scripting - Parse WHOIS/WHOWAS/LIST responses - Bracketed paste [meh, not all it's cracked up to be] - Date change messages - Channel join status indicators - Finish config fields - username for USER message (it's more restrictive than nicknames, though undocumented; perhaps just put 'yrc' here!) 6. News and contact News can be found in the yrc category on the author's blog: http://fixpoint.welshcomputing.com/category/software/yrc/ Questions/comments can be left on articles there or by visiting #fixpoint on Freenode. Footnotes [1] Inspired by DJB software, http://cr.yp.to/. [2] Not even "ncurses", a lesson learned from the first implementation. It's a mess. [3] With the possible exception of CTCP ACTION (the /me command) due to its popularity. [4] Contrary to presently popular opinion, this does not preclude non-English communication. It's simpler, and probably healthier, for people to learn "pinyin"/transliteration systems to a single alphabet, than to have every program pretend to support some Consortium's never-finished Babel of an infinite alphabet and all the related landmines. Double-width characters in fixed-width fonts; bidirectionality; combining ligatures, diacritics, and canonicalization thereof; surrogate escapes; multiple types of spaces; characters that look the same but aren't; non-standard private mappings; variable length encodings; byte orderings; decode error handling; glyph substitution because no single font designer can hope to provide complete coverage... are you scared yet? [5] Historically it's had more holes than Swiss cheese -- in design, in every major implementation -- and there's no cause to imagine that just one more patch release will fix everything. Use good cryptography if you need it, and stop deluding yourself otherwise. [6] Well, limited by your available memory. It would take a very busy channel indeed to make a serious dent in today's memory sizes, but in such a case, you can reclaim memory by closing its specific window from time to time. [7] Control and 8-bit characters plus ".", "/" and "%"; this does not include various shell metacharacters. [8] Currently this is in fact the implementation, which may result in interface lag e.g. on network filesystems. FD caching or a separate log thread are possible remedies if anyone cares.