[back]   [TOC]   [forward]


Chapter 7
Processing Commands
iSimplePlug Documentation


As described in the Plugin Registration chapter, the processCommand: method was set-up as the method in the plugin that iTonamaton calls when a command was issued on IRC. If this were a complex plugin, we would make this method determine the command given, and then delegate the actual work of the command to another method (which may or may not be in the same class). However, iSimplePlug is small and simple enough that we'll do all of our processing right in the processCommand: method.

Before continuing with an explanation of the actual code of the method, it should be mentioned that it is a convention that all commands a plugin responds to should respond to the help argument. This means that if someone types "!monkey help" in IRC, the iSimplePlug plugin should respond to this with a help message for the "monkey" command.

The processCommand: method, then, can essentially be broken into three parts: The first part is to determine the command ID of the recieved command. The second part is to determine if the command was issued with the "help" argument. The last part is an if structure which determines the command given and the course of action to take.

The text of the processCommand: method is as follows. (Note that I apologize for the length of a few of those lines, as they don't display on a narrow screen very well. However, they looked rather confusing to me when I split them up, so I decided to leave them as is.)

- (void)processCommand:(NSNotification *)notification
{
    //Get the command ID.
    unsigned commandID = [self commandFromNotification:notification];
    
    //Determine if the help argument was given.
    BOOL outputHelp = NO;
    NSArray * arguments = [[notification userInfo] objectForKey:ITCommandArgumentsKey];
    if( [arguments count] > 0 )
    {
        if( [[arguments objectAtIndex:0] caseInsensitiveCompare:@"help"] == NSOrderedSame )
        {
            outputHelp = YES;
        }
    }
    
    //Process the command.
    if( commandID == commandIDArray[0] )    //!monkey
    {
        if( outputHelp )
            [self sendMessage:@"!monkey outputs the sound a monkey makes."
            	withNotification:notification];
        else
            [self sendMessage:@"Eep!" withNotification:notification];
    }
    else if( commandID == commandIDArray[1] )    //!cow
    {
        if( outputHelp )
            [self sendMessage:@"!cow outputs the sound a cow makes."
            	withNotification:notification];
        else
            [self sendMessage:@"Moo!" withNotification:notification];
    }
    else
    {
        NSLog( @"iSimplePlug: Command ID %u not recognized", commandID );
    }
}

Retrieving the Command ID

The first thing that needs to be done is to determine what command was sent to iTonamaton. The NSNotification that is sent to our processCommand method contains this information, among other things, in it's user info dictionary (which can be accessed by calling [notification userInfo]. However, ITPlugin provides the convenience method commandFromNotification:, which does all the work of extracting the command ID from the notification for us. It then returns the resulting command ID as an unsigned value. Thus only a single line of code is necessary to rerieve the command ID for the issued command.

Determining if Help is Needed

As mentioned before, although there is nothing programmatic making it required, it is requested that all plugins respond to the "help" argument. In our plugin, I chose to make a section of the code set the local boolean variable outputHelp to YES if the help argument was given.

This block of code starts by declaring the outputHelp variable and setting its value to NO. We are assuming that no help is needed at the outset, and then attempting to prove that assumption wrong.

The next line retrieves the array of arguments that was given to the command from the passed notification's user info dictionary. This is done by retrieving the object associated with the ITCommandArgumentsKey key that is stored in the user info dictionary.

Next is an if statement that checks to make sure there are more than zero arguments; that is to say, that there is at least one argument supplied to the command. We do this because an attempt to access an argument number that doesn't exist would cause an exception that would crash the program.

Once it is verified that there is at least one argument, we check to see if the first argument (at index zero) is "help". This is done using the caseInsensativeCompare: method from the NSString class. It compares the passed string to the string it is called on, and returns either NSOrderedAscending, NSOrderedSame, or NSOrderedDescending. In our case, we want to check that the string returned by [arguments objectAtIndex:0] is the same as "help", so we check if caseInsensativeCompare: is equal to NSOrderedSame.

Lastely, if the first argument was, indeed, "help", then we set the local variable outputHelp to YES, so that the commands know to return their help information instead of doing their normal task.

Processing the Command

Now that we have the command ID of the command to process, and know whether we need to display the help message for a command or return the result of the command, we can actually accomplish the real meat of the plugin.

The first thing to observe about the code here is that the rest of the method is nothing but a big if-elseif-else construct. Each of the if statments in this construct compares the commandID against the cached command IDs to determine which command was supplied. Then, in the event that the command ID is unrecognized, the contents of the else statment are used.

It may be good to mention that although this code looks like a great candidate for the C switch-case construct, it turns out that since the elements of commandIDArray are variables, the compiler won't let us do that. Therefore the if-elseif structure is the next best option.

Now we turn our attention to the induvidual if/elseif statements. Looking inside of any of these if statments shows a nested if-else construct. This secondary if statement causes our plugin to sends the help message if the "help" argument was given, and otherwise send the command's normal message.

I would like to direct your attention to the sendMessage:withNotification: method. This method, defined in ITPlugin, is another of the convenience methods offered to plugin makers. It takes the specified message text, and sends it to the appropriate recipient, by extracting the necessary information from the notification. Note that the notification is needed because it contains the information on whom the message needs to be sent to.

Finally, there is the else statement. This else statement is not necessary; indeed it was only provided here to show how one could use an NSLog() statement to monitor an aspect of their plugin. In this case, it is a useful debugging tool for when your plugin didn't respond to the command you thought it would.

Before closing this chapter, I should note that in the implementation of iTonamaton available at the time of writing, every plugin is notified of every command--including ones it did not register for. However, in future versions of iTonamaton, it is possible that this could not be the case. At this time, the aforementioned else statment would be rendered completely useless.


[back]   [TOC]   [forward]
Last Modified: $Date: 2003/12/16 01:29:33 $ by $Author: paploo $