Table of Contents
Synopsis:
on [#][<modes>]<event-type> [<serial#>] [-|^][']<pattern>['] [(arglist)] [<block>]
on [#][<modes>]<event-type> [<serial#>] [-|^]<wildcard> [{ <action> }]
Event Driven Programming
Because the ircII language is event-driven, you control it by registering event handlers. These are also called “ONs” or “Hooks”. Most of the time, the client is sleeping, waiting for something to happen. When something does happen (if you press a key, or a server sends you something, or a timer expires), it handles it. Part of the handling is throwing an event. Through the ON command, you can have your code run when an event is thrown. The primary use of ON is to allow you to control how events are displayed to windows.
Uniqueness:
ONs have to be “unique”. The primary key of an ON is:
- Event Type
- Serial Number
- Wildcard Pattern
That means every ON has to have these three pieces of information. Creating an ON is like an “upsert” – if there is not an existing ON, you will create it. If there is an existing ON, you will update it.
Attributes:
In addition to the primary key, ONs have some attributes
- Argument List
- Code Block
- Negativity Flag
- Noise Level
- Flexible Wildcard Flag
- Global Unique Serial Number
- Skip Flag
- Filename
- Weight (the number of non-wildcard characters in the pattern)
About Events:
An event contains two pieces of information:
- Event Type (such as MSG, JOIN, KEYPRESS)
- A string of data (stored in $*)
What Happens When Events Are Thrown:
The client collects all of the ONs of the Event Type whose wildcard pattern matches the data in $*. Then, the client selects for each serial number the ON that has the highest weight. Then the ONs are executed in serial-number order.
Handling or not handling an Event:
An event is considered handled if and only if:
- You have a matching ON of the event type with serial number zero
- That ON's Noise Level is either ^, %, or ? (and it returns non-zero)
Unless these two qualifications are met, you have not handled the event.
If you do not handle an event, the client will usually perform a default action. For example, if you do not handle a MSG event, the client will output
- nick* message goes here
but this only happens after all of your ONs have run. The practical effect of this is that the client's default output occurs at the highest possible serial number, because it happens after the client has processed your ONs.
If you're doing an echo in a positive serial number ON and it's important to you that it's output after the “ordinary” stuff, then you must make sure to supply a zero-serial-number ON to do the “ordinary” output.
on ^msg * {echo *$0* $1-}
Implied ON hooks and Not Handling an Event:
Implied ON hooks work exactly the same as the client's default actions. They output something if and only if you do not handle the Event, and they do this output after all of your ONs are run, and NOT at serial number 0! If it's important that something be echod at serial number 0, then you must supply a handler to do that.
The things you can pass to ON
General syntax of ON:
ON <SNI><Noise><TYPE> <SerNum> <Remove><Not><Pattern> <Code Block>
Serial Number Indicator (SNI)
(Optional) The Serial Number Indicator is the hash (“#”) and indicates the presence of a serial number. If you don't use a serial number indicator, then the ON will use serial number 0.
Noise Indicator (Noise)
(Optional) Special characters control how the event is handled:
Explanation | |
---|---|
Character | The noise indicator special character |
Special name | How this modifier is referred to elsewhere |
Display | 1 = Output is not automatically suppressed, 0 = All commands are internally prefixed with ^ to suppress display. |
Alert | 1 = Special “ON MSG hooked by …” message, 0 = No special message |
Suppress | 1 = Suppress the default action if you run this handler. 0 = Do not suppress the default action, -1 == see note below |
Character | Special Name | Display | Alert | Suppress |
---|---|---|---|---|
^ | Silent | 0 | 0 | 1 |
- | Quiet | 0 | 0 | 0 |
Default | 0 | 1 | 0 | |
+ | Noisy | 1 | 1 | 0 |
? | Unknown | 0 | 0 | -1 |
% | System | 1 | 0 | 1 |
Please note that because non-zero serial numbers cannot handle an event, Suppress only matters for zero-numbered serial numbers. For non-zero serial numbers, there is no difference between ^ and - and ?
Event Type (TYPE)
(Required) All valid event types are returned by
$hookctl(LIST LISTS *)
Serial Number (SerNum)
(Optional) If you use the Serial Number Indicator, you must supply a Serial Number for the ON. The default serial number is 0.
…………… work in progress …………………………
Exceptive Indicator (Not)
Delete Indicator (Remove)
Wildcard Pattern
Code Block
Things that don't work together:
Examples:
Create a non-handling ON MSG to format incoming msgs:
/on msg * {echo ..msg from $0:.. $1-}
(Note that this on does not handle the event, so the normal output from the client is still going to happen)
Create an ON MSG that actually handles the event:
/on %%^%%msg * {echo ..msg from $0:.. $1-}
Create an ON MSG that saves the last time someone sent you a MSG
/on #-msg 500 * {@ last_msg_time[$encode($0)] = time()}
Create an ON MSG that tells you the last time someone MSGed you:
/on #-msg -500 * { if (last_msg_time[$encode($0)]) { @ :sec = time() - last_msg_time[$encode($0)] echo $0 MSGed you $sec seconds ago. } }
Delete all ON MSGs
/on msg -
Delete only ON MSGs for serial number 500
/on #msg 500 -
Delete only one specific ON (MSG type, serial number -100, pattern “* *”)
/on #msg -100 -"* *"
– Argument List – Code Block – Negativity Flag – Noise Level – Flexible Wildcard Flag – Global Unique Serial Number – Skip Flag – Filename – Weight (the number of non-wildcard characters in the pattern)
The Order of Things:
First Argument:
Numeric Indicator:
This is optional. If you intend to use a serial number, put a hash ('#') at the start of the first word before everything else.
Noise Modifier:
Special note about “Unknown” modifier: Your event handler is expected to return a value. If it returns zero, then the default action will not be suppressed. If it returns non-zero, the default action will be suppressed.
Event Type:
First Argument (Part Two):
This is optional. If you are using a serial number, put it in the word immediately after the Event Type. You must have a hash as the first character in the first word if you use a serial number, and you must have a serial number if you use the hash. It has to be both-or-neither. Failure to follow this rule will cause your on to be mis-parsed.
The serial number may be a number, or it may be the literal characters plus (“+”) or m
Second Argument:
Hyphen for removal:
If you prefix the second argument with a hyphen ('-') then it will remove the on for that type for that serial number for this pattern. If you do not specify a pattern in the second argument, then it will delete *all*
NOISE MODIFIER (optional):
SERIAL NUMBER (optional):
Every on has a serial number. The default is 0. If you want to use a different serial number, you must prefix the event type and noise modifier with a hash (“#”), and the serial number must be the first argument after the event type.
Again, to be absolutely clear about this, if you use both a serial number and a noise modifier, the hash must go first, then the noise modifier, then the event type.
Further, to be absolutely clear about this, if you tell the client you want to use a serial number, it must be after the event type and before the wildcard pattern (see below).
WILDCARD PATTERN (optional):
After the event type is the wildcard pattern which tells
Serial Number:
Every ON has a serial number. The default is 0. If you want to specify a serial number, the first character of the first argument must be hash (“#”) and the second argument must be a number, which is the serial number.
If you forget to prefix the first argument with a #, your serial number is liable to be mis-interpreted as a numeric reply handler.
If you prefix he first argument with a # but forget to include the serial number, your pattern is likely to be mis-interpreted as a number and your on will be defective.
If you want to use the default serial number 0, do not prefix the first argument with # and do not specify a serial number as your second argument.
Event Type:
Every ON has an event type. All valid event types are returned by:
$hookctl(LIST LISTS *)
Registering an /on for an invalid event type will fail.
Event driven programming:
The client uses an event driven programming model. The on command lets you register event handlers which will be called whenever an event occurs that qualifies according to the criteria of your event handler.
An ON has three basic criteria for being triggered: 1. An “event type”, such as MSG or JOIN or PUBLIC 2. A “serial number” which controls the sequence the event handlers are processed. 3. A “pattern” which allows you to catch only events you are interested in (based on $*)
Whenever the criteria of your event handler is satisfied, the “block statement” will be executed. You may optionally provide an arglist to process $* in the same way alias_command does.
How events get processed
Whenever an event is generated, the client evaluates all of your ONs to decide whether or not the event is “suppressed” or “not suppressed”
1. If @hookctl(DENY_ALL_HOOKS 1) is turned on, the event is “not suppressed” 2. If there are no /ONs for the event type, the event is “not suppressed” 3. If there is no implied on for the event type, the event is “not suppressed”. 4. If the event has recursed, and that event forbids it, the event is “not suppressed”. 5. For each serial number, the client determines which /ON “best matches” $* and collects all of thsoe /ONs into a list. 6. If an /ON has a “flexible pattern” then the order it is expanded relative to other /ONs is unspecified. 7. If an /ON is “skipped” it cannot be the “best match” 8. If you did a @hookctl(HALT_CHAIN -1), then no /ON will be the “best match” 9. If there is no “best match” for a serial number, go back to #5. 10. If the “best match” is a “excepting” on, go back to #5. 11. If the serial number is 0 and the “best match” is a suppressing handler, then the event will be “suppressed” 12. If the serial number is 0 and the “best match” is a pending handler, then the event will be “suppressed” if the block statement returns a numerical value other than 0 it will be “not suppressed” if the block statement returns anything else. 13. If the “best match” is a “noisy” handler, then a message will be displayed to the screen that the handler has been executed. 14. If the “best match” is a “silent” handler, then the block statement will be executed as though each and every statement within it had been prefixed with a ^.
Unless the event was suppressed (per #11 and #12 above), the event is considered “not suppressed”
If an event is “not suppressed”, the client may perform some default action. For example, the default action of /ON MSG is:
echo *$0* $1-
Doing a return within the block statement of an on that is not a “pending” has unspecified behavior.
From time to time, important events will occur. An example of events are someone joining a channel, saying something on a channel, or leaving irc. Each time something interesting happens, an event is posted by the client. You can tell the client you want control to be returned to your script when certain types of events occur. Event handlers are created with the on command.
Events contain two piece of information, a type and data. The type is used to categorize events: when someone talks on a channel, that is an PUBLIC event. When someone sends you a msg that is a MSG event. When someone joins a channel, that is a JOIN event. The data is information that is specific to each event that is thrown. A JOIN event contains the nickname of the person who joined, the channel they joined, and their user@host.
At the most fundamental level, you can hook an event by providing both a type, and a wildcard pattern to match the data.
on msg * { echo $* }
This hooks all msg events and runs a simple command.
When your script is finished processing the event, control returns back to the client. Usually the client will perform some default action in response to each event. Because most events have default actions, this means if you don't hook an event, something reasonable will still happen.
Noise modifiers:
One of the first things people want to be able to do with event handlers is replace the default action with their own custom action. If you tried the above example, you noticed that your event handler was performed in addition to the default action. This is the default way events are handled.
Every event handler has a noise modifier which is set by a special character that prefixes the type. This modifier tells the client how it should behave when this event handler is executed.
So if we wanted to change the above example to do our echo and not the default action:
on ^msg * { echo $* }
The ^ before the msg means this event handler is “Silent” which means the default action should be suppressed.
About "actions":
The “action” of an event handler is a block of ircII script that should be executed every time that this handler is considered the “best” match at the current serial number for the current event.
If you prefix the “match pattern” with the caret character (``^''), then you should not provide the “action”; EPIC will perform no action when this event handler is used. This is not backwards compatible with very old versions of ircII and is not particularly recommended.
If you prefix the “match pattern” with the bang character (``!''), then you should not provide the “action”; EPIC will perform no action when this event handler is used. THIS IS NOT SUPPORTED IN EPIC4 – DO NOT USE THIS FEATURE IN EPIC4. Watch this space for more details how this will work in EPIC5.
More about "events" in general:
[...]
The text matched for the hook is also rather versatile. In the match string, any wildcard may be used. The match must be surrounded by quotation marks (unless it is a single word). If double quotes (“) are used, the match string is evaluated when the hook is defined. If single quotes (') are used, the match string is taken literally and evaluated each time the event is hooked. This allows for variable matches to be used. Additionally, the match string may be prepended with its own mode.
- This isn't really a mode, per se. Rather, it is used to remove
| any hook with the same match string. If no match string is
| given, all hooks for th given event are removed. ^ The exclusion mode. This causes the client to do nothing when | the hook is triggered with the given match. It is effectively | the same as only using a [[COMMENT]] in the action, or some other | noop command.
The last part of a hook is the action. This defines what the client is supposed to do when a hook is triggered. The action can be just about anything the user wishes. The syntax works basically the same as with ALIAS. Braces are only required for multi-line actions. Also, as with aliases, hook actions can receive and use numeric expandos (representing the full event arguments hooked).
Also, if this command is given with either none or a single argument, it will list all currently defined hooks matching the argument.
Examples:
To redefine the default JOIN message:
on ^join "*" { echo ^VB^V*>*^VB^V $0 \($2\) has joined $1 [$Z] }
To suppress channel messages from users from certain sites:
assign ignore_em *@*.msn.com *@*.aol.com *@*.goodnet.com on ^join ^'% % \\[$ignore_em\\]'
To remove all hooks for a particular event:
on join -
To show an additional message for a certain site, after the default:
on #-join 10 "% #blah %" { echo ^VV^V***^VV^V Oh great, yet another person has joined $1 }
Other Notes:
ON allows for a great deal of automation of client activities. This can be a bad thing if abused. For instance, using it to automatically send a greeting to anyone joining a channel is usually considered bad form. Let common sense dictate when an automated response is appropriate.