ERC hooks and nifty functions

(Be careful, this is a fairly advanced topic. If you don’t intend to hack on ERC, skip this section, as it will most probably only serve to confuse you.)

ERC is a nearly completely hook-driven IRC client. The three most important hook types in ERC are:

There are also some hooks not related to the IRC protocol, covered in the miscellaneous hooks section.

Another nifty topic that somehow fits here (from the programmatic viewpoint) is ERC commands.

These hooks are covered in detail in the following sections.

Miscellaneous hooks

‘erc-before-connect’ is called before connecting to a particular server.

‘erc-after-connect’ is called after the server sends its MOTD.

‘erc-mode-hook’ is called for each ERC buffer, be it a server buffer, channel buffer, or otherwise.

‘erc-join-hook’ is called when ERC joins a new channel.

‘erc-timer-hook’ is called every time something is received from the server. Note that this is not a true timer, so if there’s no activity on the server for a while, it’s possible to have a timer event take place minutes after you’d like it to happen.

Server hooks

The RFCs that define IRC (see for that) specify that the server must send lines in a special format to the client. These consist of an optional prefix (the sender) and a command, which can be:

If ERC receives one of these commands, it parses the message and extracts the command. Then, the hooks come to play: It runs the hook called `erc-server-<command>-functions’. In this hook, there can be a default handler (most often called `erc-server-<COMMAND>’). If the hook is empty (‘nil’), ‘erc-default-server-functions’ is run. You can set this hook to catch all unhandled server replies somehow…

All the server hooks are run using ‘run-hook-with-args-until-success’, which means that if a function of those hooks returns t, the rest of the hook is skipped. Use this method to prevent other hook functions from executing. See also the macro erc-once-with-server-event which can be used to catch the next arrival of a certain event type and prevent processing it. This macro is used in erc-notify and erc-list.el.

It is a good idea to have functions that are called from server hooks return nil if you’d like other functions, such as the default handler, to be called as well.

ErcBbdb makes use of the hook system to enhance the functionality of the /whois command, as well as JOIN messages.

CTCP hooks

As details, CTCP messages are used to send extended data between clients. Examples are actions generated by the /me command, and reply-request pairs such as a ping request and its response. An action or CTCP request is sent in a PRIVMSG, and a reply to a CTCP request is sent in a NOTICE. CTCP messages follow this syntax: The first character is a ^A, and that is followed immediately by the message type (e.g. ACTION or PING). If there are any parameters (e.g. the arguments to the /me command, or a time-value for a ping request or response) then there is a space followed by those parameters. Finally, the CTCP message is terminated by a second ^A.

ERC extracts from the message its type, and runs a hook. As in the server messages, there are default handlers for CTCP messages which reply to CTCP messages.

CTCP hooks are divided into two groups:

You can, of course, define your own hooks for CTCP messages. As stated in ErcTODO and ErcBbdb, it will soon be possible to send BBDB records to other ERC users.

ERC display and input hooks

The user interface basically has two types of event where hooks are used: One for when something needs to be displayed and another for when the user gives ERC input.

Display hooks

There are three hooks you can use for a display event:

  1. ‘erc-insert-pre-hook’. As the name implies, this first one can be used to prevent display of a certain text string entirely, or do some preprocessing. It can’t modify the displayed text, but it can set a flag called ‘erc-insert-this’, which specifies whether the text should be inserted into the buffer or not.
  2. ‘erc-insert-modify-hook’. This hook is run after the actual text is inserted. While it runs, the buffer is narrowed to the inserted text using narrow-to-region. Thus, you can use (point-min) and (point-max) to determine start and end of the inserted text on the modify hooks.
  3. ‘erc-insert-post-hook’. This hook is run after the modify hook. It should not modify the text itself, and is intended for functions which need to be run after all potential modifications. ‘erc-insert-post-hook’ functions can still modify text properties, e.g. toggle the read-only property or highlight text.

Input hooks

The same applies for input hooks. These are called:

  1. ‘erc-send-pre-hook’, which can additionally set a flag (‘erc-send-this’) if the text should not be sent,
  2. ‘erc-send-modify-hook’, and
  3. ‘erc-send-post-hook’.

Also, note that the modifying hooks (2 and 3) only modify the text that is displayed to the user, not the text that is actually sent.

ERC Commands

As you might have noticed from the previous subsections, I have stressed that for each server or CTCP message that ERC receives, a hook with a special name is called. We have taken that idea further by applying it to commands as well. For example, when you type /JOIN, ERC calls a function called ‘erc-cmd-JOIN’ (note the case of the word, it’s important).

So, defining your own /-commands is easy: Just write a function called `erc-cmd-<command>’.

The /HELP command is interesting: When you call it, ERC uses ‘apropos’ to find all functions beginning with ‘erc-cmd’ and displays these and their documentation strings.