Script Input Handling

KosmicTask Help

Script Input Handling

Each task has an associated script that is run whenever the task is executed. Tasks can optionally accept inputs that are passed directly to the script. Whenever a task is run KosmicTask has to:

  • Call the script.
  • Allow the script to access the task inputs in the correct order.

Each support scripted language has a separate task runner that is loaded whenever a task is executed. The task runner is responsible for loading the script, preparing the task inputs, executing the script and returning the result. Each task runner executes all of its scripts either in-process or out-of-process and this affects how inputs are passed to the script. The process type for any scripting language is displayed in the resource browser settings page under the title Executable Process Type.

Task inputs are passed to the script in the order that they appear within the task. As an example consider a simple task that accepts three inputs arranged as follows:

  1. Name. User name as represented by a text type input. Default is Hubert Muggins.
  2. Weight. User weight in kilos as represented by a number input type. Default is 60.
  3. Date of Birth. User date of birth as represented by a date type input. Default is 1966-12-25.

When the task is run the task script will receive the inputs in the above order. If there is ever any doubt on how to access script parameters in a particular language the easiest solution is often to consult the Argument List template within the Resource Browser.

Running Out-of-process Scripts

An out-of-process script is one that is run using a separate subsystem that is generally an instance of a command line shell or interpreter. Scripts of this type return results to the user by writing to stdout, an operation that is generally achieved using some form of 'print' or 'echo' command. In the following out-of-process script examples the task inputs are read in as command line parameters. With the inputs described above supplied each of the example scripts produces the following output:

Hubert Muggins
60
1966-12-25 16:56:16 +0000

Out-of-process Script Input Examples

echo $1
echo $2
echo $3
class kosmicTask
{ 
    public static void main(String args[])
    {
        System.out.println(args[0]);
        System.out.println(args[1]);
        System.out.println(args[2]);
    }
}
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("%s\n",argv[1]);
    printf("%s\n",argv[2]);
    printf("%s\n",argv[3]);

    return 0;
}
#include <iostream.h>

class KosmicTask {  
    public:           
  
    KosmicTask(int argc, char *argv[]) { 
        cout << argv[1] << end;
        cout << argv[2] << end;
        cout << argv[3] << end;
    } 
};
 
int main(int argc, char *argv[]) 
{
    KosmicTask *kosmic = new KosmicTask(argc, argv);
}
puts  [lindex $argv 0]
puts  [lindex $argv 1] 
puts  [lindex $argv 2] 

Out-of-process Script Settings

Each scripting language plug-in defines a number of settings that are applied to a task. Many of these settings are read only but some can be modified to change the operation of the task. The various settings for each language can be viewed and modified via the resource browser settings.

Most of the out-of-process languages support some or all of the following settings:

Build Options
A list of optional parameters to be passed to the script build program. These options generally correspond to the build program's command line options.
External Build Path
The path to the external build program. This program will be invoked when the task is built. This option is normally provided for languages supplied as part of OS X and the default value points to the system supplied build program or compiler. For example, in the case of Java, the build path defaults to /usr/bin/javac. Changing this value allows the task to use an alternate build program. In many cases the build path and the executable path will be the same. This means that the program at the executable path is capable of verifying the script without executing it. KosmicTask will set the appropriate command line option whenever a build is request.
Executable Options
A list of optional parameters to be passed to the script executable program. These options generally correspond to the executable program's command line options.
External Executable Path
The path to the external executable program. This program will be invoked when the task is run. Again, this option is normally provided for languages supplied as part of OS X and the default value points to the system supplied executable program. For example, in the case of Java, the executable path defaults to /usr/bin/java. Changing this value allows the task to use an alternate executable program.

Some out-of-process scripts may also support one or more of the settings listed below for in-process scripts. For instance, Java supports the Run Class setting to identify the public class containing the static main function.

Running In-process Scripts

In-process scripts do not rely on an external shell or interpreter in order to build and execute a script. Instead, the scripting language task runner directly builds and executes the script. This is achieved by incorporating the relevant scripting libraries into the task runner itself. This has the advantage of allowing a much greater degree of interaction between KosmicTask and the scripting language itself. In particular it means that inputs are not retrieved from the command line but are passed into an input function that is called whenever the task is run. A further effect is that in some cases native language objects can be returned as results. All of the Cocoa bridges supported by KosmicTask are implemented as in-process scripts.

An in-process script normally generates a result by returning a value from its input function rather than by writing to stdout. The following examples demonstrate how to pass inputs into various in-process scripting languages.

on KosmicTask(name, weight, dateOfBirth)
    return name & return & (weight as integer) & return & dateOfBirth
end KosmicTask
[:name :weight :dateOfBirth |	
    name ++ '\n' ++ (weight description) ++ '\n' ++ (dateOfBirth description)
]
function kosmicTask(name, weight, dateOfBirth) 
{
    // return the argument list as a string
    return name + '\n' + weight + '\n' + dateOfBirth;
}
function kosmicTask(name, weight, dateOfBirth)
    return name .. '\n' .. weight .. '\n' .. dateOfBirth
end
require 'osx/cocoa'
def kosmictask(name, weight, dateOfBirth)
    return name + "\n" + weight.description + "\n" + dateOfBirth.description
end

Many of the Cocoa bridges also support the subclassing of Cocoa objects. In these cases the input function may reside within a class as in the following example.

import Foundation
class KosmicTask (Foundation.NSObject):
    	
    #
    # task entry point
    #
    def kosmictask(self, name, weight, dateOfBirth):	
        return name + "\n" + weight.description()  + "\n" + dateOfBirth.description()

In-process Script Settings

Languages that run their task scripts in-process with the task runner generally do not call upon an external program to execute or build the script hence the external path settings described above are normally not defined. In some cases however, for example AppleScriptObjC, an external tool is used to build the script but the execution is carried out in-process.

Most of the in-process languages support some or all of the following settings:

On Run Task
A value determining how the task calls the script and passes in the input values. A particular language may support one or more of the available options.
  • Call Script. Calls the script and makes task inputs available as command line arguments.
  • Call Run Function. Loads the script and calls the named run function, passing any task inputs to it.
  • Call Run Function on Run Class. Loads the script and calls the named run function on the named class. Task inputs are passed to the run function.
Run Class
The name of the class containing the run function.
Run Function
The name of the run function to be called when the task is run.
Default Run Class
The default value for the run class.
Default Run Function
The default value for the run function.

Calling an In-process Script

The effect of the various in-process settings can be demonstrated by considering a number of example AppleScripts. Although the examples here use AppleScript the general approach applies to all languages. An AppleScript script can be called without defining a run function as in the following case. Not all in-process languages support this feature (though most out-of-process certainly do) but if they do then the Call Script option will be available for the On Run Function setting.

return "This task has no inputs"

For the above script to run correctly the On Run Task setting must be set to Call Script. If the On Run Task value is incorrectly set to Call Run Function then the following error will occur when the task is run:

Error Domain=KosmicTask Runner Code=2002 "Script execution error"

In general an error may occur if the task runner cannot find the named run function in the script. Each template defines its own settings so using a template as the basis for any script will ensure that the correct initial On Run Script setting will be applied.

A feature peculiar to AppleScript is that even if no run function is defined AppleScript implements an implicit run handler. This run handler can be made explicit and may be called with or without arguments:

on run {}
    return "This task has an explicit run handler and no inputs"
end run
on run {myInput}
    return "The task input is : " & myInput
end run

KosmicTask will successful call the above two scripts with On Run Task set to Call Script or with On Run Task set to Call Run Function and Run Function set to 'run'.

Setting the Run Function

When calling a specific run function the Run Function setting is used by the task runner to find the script entry point. All of the language plug-ins and templates default to using 'KosmicTask' as the default run function name. For the following example to run correctly On Run Task must be set to Call Run Function and the Run Function setting must remain at its default value of 'KosmicTask'

on KosmicTask(myInput)
    return "The task input is : " & myInput
end KosmicTask

To change the script entry point we edit the script as below and set Call Run Function to 'myHandler':

on myHandler(myInput)
    return "The task input is : " & myInput
end myHandler

If the task runner cannot locate the run function then a run time error will be reported when the task is executed. The above example accepts one input, the example below, two.

on myHandler(myInput, anotherInput)
    return "The task inputs are : " & myInput & " and " & anotherInput
end myHandler

In general the number of run function arguments must match the number of task inputs. If the run function contains more arguments than there are task inputs then a run time error will occur. If the task contains more inputs than there are script arguments the extra inputs may be ignored or a runtime error may occur depending on the language being used.

Setting the Run Class

AppleScript does not permit the definition of a Run Class but RubyCocoa, in common with most of the other Cocoa framework bridges, does. When using a class function as the script entry point On Run Task must be set to Call Run Function on Run Class. The following example calls the default 'kosmictask' run function on the default 'KosmicTask' class:

require 'osx/cocoa'
class KosmicTask < OSX::NSObject
		
    #
    # task entry point 
    #
    def kosmictask(myInput)	
        return myInput	
    end
end

To change the script entry behaviour as in the next example set the Run Class to 'MyTask' and the Run Function to 'myFunction'.

require 'osx/cocoa'
class MyClass < OSX::NSObject
		
    #
    # task entry point
    #
    def myFunction(myInput)	
        return myInput	
    end
end