Scripting     Basics    AppleScript     IrcII scripting
Download
Features
Screenshots
Version History
Registration
Contact



Snak Manual

Introduction
Quickstart
Connecting to a server
Joining channels
Sending messages
Actions
Keeping track of people
Customization and settings
Using DCC
IRC commands
Scripting
Troubleshooting

 

AppleScript

AppleScript is a scripting language. Scripting languages have all the capabilities of other programming languages, but are easier to use because their structure is closer to everyday English.

AppleScripts can store data for later use and examine their surroundings to determine what to do next. They can also loop through certain instructions, repeating them as many times as you like, or until something specific happens. These features, and others, are what makes a scripting language - particularly AppleScript ideal for anyone that wants to automate a task.

AppleScript is different from other scripting languages because its reach isn't limited to a single application. AppleScript is part of the Macintosh operating system, and that enables it to work with several different applications at once if necessary. You can extract data from one application and hand it to another for processing with AppleScript, and it can even be used to control other Macs over the network.

How to start

There are many good books about AppleScript, and I can in particular recommend "The TAO of AppleScript" by Derrick Schneider and "AppleScript Language Guide" from Apple.

In order to write an AppleScript that uses Snak, you need to open the Script Editor application that was installed as part of your operating system. It is found in the AppleScript folder in the Applications folder.

There are five main parts to AppleScript:
  • Objects - which points to items and information inside the application
  • Commands - which acts on those items and information
  • Variables - which allows you to store data for later use
  • Conditionals - which enable your script to make decisions based on a set of conditions
  • Repeat loops - which give you the capability to execute commands repeatedly

Every scriptable application contains a dictionary of the commands and objects it knows about. To see the Snak dictionary, run the Script Editor and select "Open Dictionary" under the file menu and select the Snak application:

Under the heading "Snak Suite" you see all the commands you can send to Snak -

  • connect - sent to an IRCConnection object to open a connection.
  • disconnect - sent to an IRCConnection object to close a connection.
  • echo - sent to a target (a channel, filter, query etc.) to display a message locally. The message is not sent out.
  • type - sends a command or message to a specific target as if the user had typed it directly.
  • match - used for fast matching of strings against a pattern.
  • store data - used to let a script store a setting in the Snak preference file.
  • load data - used to let a script retrieve a setting from the Snak preference file.

Command provided for compatibility with older scripts:

  • do - sends a command to a specific target as if the user had typed it directly.
This command should not be used in new scripts.

and all the objects you can access through AppleScript -
channels, connections, users, ignoreitems ... and many more.

In the dictionary you will notice that in order to access some objects you have to go through other objects. This is called an object hierarchy.

Snak's object hierarchy is:
  • The application contains connections (and more)
  • A connection contains channels (and more)
  • A channel contains users (and more)
Your first AppleScript

This is an example of a simple, yet (somewhat) useful little script. Once it's loaded into Snak you will be able to type "/countops" to have the script tell you the ratio of channel operators to normal users. The script asks Snak how many users are in the current channel, and how many ops there are among them. Then it calculates the ratio and displays a message.

Open the Scripts folder by choosing "Show Script Folder" in the windows menu. That will cause the Finder to display the folder where it is. Open the folder itself by doubleclicking it.

In this folder is a script called "countops". Double click this file to open the Script Editor. This will open a window with the text of the script. I have added the line numbers for convenience.

line 1: on run
line 2:      tell application "Snak"
line 3:           set n to NumberOfUsers of channel CurrentChannel of connection CurrentConnection
line 4:           set ops to count (get (every user whose op = true) of channel CurrentChannel of connection CurrentConnection)
line 5: 
line 6:           if n > 0 then
line 7:           	set percent to ops / n * 100 as text
line 8:           else
line 9:           	set percent to 0 as text
line 10:         end if
line 11:
line 12:         set percent to (round (percent + 0.49))
line 13:         set CommandString to "/me sees " & ops & " gods and " & n - ops & " mortals on " & currentchannel & ". 
line 14:              " & percent & "% of the people in " & CurrentChannel & " are gods."
line 15:         do CommandString
line 16:     end tell
line 17:end run

The above script shows examples of objects, commands, conditionals and variables. The bold words are part of the AppleScript language itself, and the Script Editor will automatically format them.

Starting with line 1: "on run" this is a line that tells Snak in what situation to run the snippet, namely when the uses types "/countops". Other situations are explained later when event handlers are introduced.

Line 2: "tell application "Snak"" is used by the AppleScript system itself and is used to set the target for the following block of AppleScript. Notice how the Script Editor automatically indents the following block.

Now we get to the core of the little script, the place where the interesting action takes place. Line 3 uses both objects and a variable.

"set n to NumberOfUsers of channel CurrentChannel of connection CurrentConnection"

Just relax and stay calm even if this seems like total gibberish. It is entirely logical and straightforward, once you learn how to recognize the individual pieces.

Here we ask Snak a complex question - how many users are there in the current channel on the current connection, and we store the result into a variable called "n". The channel and the connection are examples of objects.

A central concept in understanding AppleScript is that most scriptable applications have an "object hierarchy" meaning that objects are nested inside each other. You ask the top object (the application) for an object (the connection) that contains your ultimate goal (the channel), and then you ask that channel object for specific information like the number of users.

Line 2: "tell application "Snak"" which you saw first points out the top object (the application) and the "set n to ..." line will first ask for the connection from the application, and then ask for the channel from the connection, and then it asks the channel for the number of users. Try and read the line from the right and you will see the sequence.

Trust me, once you understand the idea it really makes sense :-)

Line 4 is quite complex.

"set ops to count (get (every user whose op = true) of channel currentchannel of connection currentconnection)"

Like line 3 it uses a variable and objects, but it also introduces a conditional operation. Again we find a channel object but this time we ask it for a list of all users in the channel whose "op" status is true, meaning that they are channel operators. Then we take the number of results and store in a variable.

The "whose" conditional allows you to easily gather a collection of objects that satisfy a condition.

The next few lines perform the ratio calculation, and put together the string of text that Snak should display with the result.

"set CommandString to "/me sees .."

This line looks difficult, but all it does is to pull together the information we've already found, and fill out a variable that holds a line of text. The '&' character is used to concatenate two pieces of text.

You may recognize "/me" as a Snak command, but this line just puts together a line of text that starts with the "/me" command. The line is stored in a variable called "CommandString".

As you look at the line you can recognize the variables that were defined above to hold the number of users, the number of ops and the ratio. If for example, there are 4 users on channel #macintosh, 2 of which are ops the string will end up looking like this:
"/me sees 2 gods and 2 mortals on #macintosh; 50% of the people in #macintosh are gods"

"do CommandString"

Finally we get to do an actual AppleScript command. We have a potential point of confusion here because we are mixing two different kinds of commands. There are normal Snak commands like you type in at the command line like "/me", and then there are Snak AppleScript commands like "do". The "do" Snak AppleScript command makes Snak execute a normal command as if you typed it in through the command line.

That means that you have access to all the built in Snak commands as well as any commands you define in the existing ircII language, from within an AppleScript.

So the "do CommandString" line simply executes the "/me sees ..." command as if you had typed it in yourself, which result in the ratio of ops to normal users being written out and sent as an action message to the channel.

How to load and run AppleScripts

In order to use an AppleScript it needs to be loaded into Snak. Type "/load scriptname" to make Snak read in and prepare the script to be run. If you have a handler in the script called "on load" it will be called right away. Snak will also look for a handler called "on idle" and start executing it if it's present.

If you type the name of the script as a command, the "on run" handler in the script will be run. At this time it's not possible to pass parameters to an AppleScript command, so you are encouraged to use the ircII language to write command aliases. This shortcoming will be remedied.

During development of an AppleScript it's frequently useful to unload an existing script in order to modify it and try again. To unload an a loaded AppleScript type "/unload scriptname".

Snak implements a number of event handlers that enable you to implement extensive functionality and the number of handlers will be improved in the next version. I welcome your feedback and suggestions so be sure to let me know if you need a particular feature.

Event handlers

You can write simple command aliases in AppleScript, but the real power comes when you use "event handlers". These are snippets of AppleScript that you write and load into Snak. The events in an Action is another example of event handlers, except that the events in an Action comes with a predefined set of responses. If you write your own event handler in AppleScript you have complete freedom.

Snak will call your event handlers when particular events happen, like someone joining a channel, leaving a channel, saying something, sending you a private message and more. The event handlers lets you truly customize the way Snak works and responds to events.

Example: If you are an IRC server operator you will get a number of messages from the network itself about the various going ons. This may become annoying if the messages are of no relevance to you.

With AppleScript you now have a way to intercept those messages and process or discard them without cluttering up the channels you are in.

Snak will, during its processing of the numerous different events, call some user-defined "hook functions" or event handlers. Depending on the output of these event handlers, Snak may or may not continue processing the event. This means that the user now has the ability to tailor Snak much more closely to his or her needs than ever before.

Snak comes with the script file SnakEventHandlers which contains examples of all the event handlers that Snak currently supports, and shows what parameters they require.

The following example employs an event handler called "on servernotice". Snak will call the servernotice handler whenever it receives a notice from a server as opposed to a normal user. The example script will then examine the text of the notice and if it contains the string [CLONES] the message will be redirected to a custom window in order not to clutter up the regular channel.

Notice how the return value of the handler in the case of a [CLONES] message is true. This means that the script has completely processed the event and Snak should not process it as well.

on servernotice(con, source, sourcehost, target, thestring)
     set eventhandled to false
     tell application "Snak"
          try
               if thestring contains "clones" then
                    tell connection con
                         echo thestring in filter "[CLONES]"
                    end tell
                    -- true tells Snak that this event is completely handled
                    set eventhandled to true
               end if
          end try
     end tell
     return eventhandled
end servernotice

on load() tell application "Snak" set con to currentconnection tell connection con type "/window new name [CLONES]" echo "Clone catcher" in filter "[CLONES]" end tell end tell end load

The script uses the custom windows feature of Snak. The line "type "/window new name [CLONES]" will open a custom window that you can use to display text that is filtered out of somewhere else. Such windows are called filter windows.

Stacked event handlers

Snak allows you to have multiple AppleScripts loaded and each of the scripts can implement whatever event handlers it wants. Snak will then call each event handler in turn until one of them returns true, meaning that the event was completely processed.

Snak comes with some sample event handler scripts that illustrate this. If you examine the input1 and input2 scripts in the script folder you will see that they both have an on input handler. If you load them with "/load input1" and "/load input2" and type the text that triggers the action, you will see that both handlers are called.

Likewise, idle handlers can be stacked. The idle1 and idle2 scripts both contain idle handlers and if you load them with "/load idle1" and "/load idle2" you will see periodic messages coming from both of them.

This support for stacked handlers will eliminate much complexity from large script packages.

 

Snak is Copyright © 1997-2006 Kent Sorensen. All Rights Reserved.
Logo design by energetics-design.