Generating Task Results

KosmicTask Help

Generating Task Results

A task script may generate two different types of results:

Simple Result
A simple result is a string of characters representing either a block of text or a textual representation of a number or other object such as a date. All of the supported scripting languages can return simple results.
Complex Result
A complex result is a structured object that contains one or more parts and can retain type information for each part. Complex results may also incorporate styling information that can be used to format the displayed result. All of the supported scripting languages can generate complex results.

Generating Simple Results

A simple result is generated by returning a character string. Script types that are run out-of-process by their task runner can return a simple result by writing to stdout as in the following examples:

echo "Some"
echo "Mexican"
echo "Vultures"
echo "Enjoy"
echo "Making"
echo "Jam"
echo "Sauce"
echo "Using"
echo "New"
echo "Plums"
puts "Some"
puts "Mexican"
puts "Vultures"
puts "Enjoy"
puts "Making"
puts "Jam"
puts "Sauce"
puts "Using"
puts "New"
puts "Plums"

Everything written or printed to stdout automatically becomes part of the result regardless of whether it is output using one statement or numerous statements. Script types that are run in-process by their task runner can generate a simple result by returning a string from their run function:

function kosmicTask() 
{
    var planets = "Some\nMexican\nVultures\n";
    planets += "Enjoy\nMaking\nJam\nSauce\n";
    planets += "Using\nNew\nPlums";

    return planets;
}
on run
    return "Some
Mexican
Vultures
Enjoy
Making
Jam
Sauce
Using
New
Plums"
end run
import Foundation
class KosmicTask (Foundation.NSObject):
        
    #
    # task entry point
    #
    def kosmictask(self):

        # create NSMutableString instance
        result = Foundation.NSMutableString.new()
        result.appendString_("Some\nMexican\nVultures\n")
        result.appendString_("Enjoy\nMaking\nJam\nSauce\n")
        result.appendString_("Using\nNew\nPlums")
                                
        # return object
        return result

The last example above returns a string that is constructed using a foundation framework supplied mutable string object but KosmicTask still interprets it as a simple result.

Generating Complex Results

A complex task result can return structured information in the form of lists and dictionaries. The ability to maintain a precise structure in a result is often vital when generating information that will subjected to further processing, saved to disk or used as an input to another task. Complex results can be generated by all the supported scripting languages but the exact syntax used can vary depending on the capabilities of the language and the language plug-in. In all there are three different methods that may be employed to generate a complex result though it should be noted that KosmicTask does not differentiate between them. In the majority of cases it should be apparent which method provides the most convenient means of producing the required result. The three methods may be summarised as follows:

Structure the Result Using YAML

YAML is a straightforward, human readable format for representing structured information. By creating a correctly formatted YAML string any task can return an arbitrarily complex result. All of the supported scripting languages can generate complex results in this way. The methods described below detail more flexible methods of generating complex results but directly outputting YAML is the only way that that some of the languages, such as Bash and the other shells, can return a complex result.

YAML supports two formats. An indented block format and an in-line flow style. The latter flow style format is a superset of JSON meaning that tasks can return JSON formatted strings as complex results.
Generate a Result using the Task Controller
Some language plug-ins include support for a task controller object that can take a native language object, such as a list or dictionary, and format it as a KosmicTask complex result. The task controller does this by automatically converting the structure of the native object into YAML.
Return a Native Object as the Result
Some language plug-ins, notably those that run their scripts in-process within the task runner, can return native language objects directly as complex results. This is possible because the task runner has direct access to the native object and access each element of it directly.

All languages can return results by directly outputting YAML but two language settings within the Result Representation group indicate wether a language supports either of the other two methods. The settings are:

Support for Native Objects As YAML
If Yes then a controller object is available that can automatically output a native object as YAML. The following languages support this option:

Java, Javascript, Lua, Perl, PHP, Python, Ruby, Tcl

Native Objects as Results
If Yes then native language objects can be returned as task results. The following languages support this option:

AppleScriptObjC, AppleScript, F-Script, JSCocoa, Lua Cocoa, PyObjC, RubyCocoa

Structure the Result using YAML

To generate a result using YAML the task has to return a correctly formatted YAML string. YAML does not use tags like XML and the format is easy to generate even from shell scripts. The actual YAML format itself is human readable and features both a 'block' and an 'in-line or flow' style. The YAML document marker, '--- ', must be used to indicate the presence of a YAML formatted complex result. KosmicTask will attempt to format any string result that begins with the document marker as a complex result. If an error occurs for any reason while attempting to format the complex result, say due to an incorrectly formed YAML string, then the result is returned as a simple string result.

Complex results can be composed of lists or dictionaries each of whose elements can themselves be a list or dictionary. The YAML block list format uses hypen+space to mark a new item in a list:

---
- Sun
- Mercury
- Venus
- Earth

The YAML in-line list format (JSON compatible) uses comma+space separated list items within square brackets. The following is equivalent to the previous example.

--- [Sun, Mercury, Venus, Earth]

The YAML block dictionary format uses colon+space to separate keys from values. The in-line format (JSON compatible) separates the dictionary items with comma+space in curly braces:

---
# comments begin with a hash

# block format dictionary
name: Earth
radius: 6371
satellites:
 - Moon

# in-line format dictionary
--- {name: Earth, radius: 6371, satellites: [moon]}

The hierarchy of elements with a YAML block format document is controlled by indentation. Child elements must be indented more than their parent and sibling items must have the same level of indentation. The actual amount of indentation used is not important.

The official YAML documentation describes the serialisation language in detail but effective complex results can be generated using just the features described above. The following examples all generate complex results by directly outputting YAML:

# block YAML
echo "---"
echo "- name: Mercury"
echo "  radius : 2440"
echo "  satellites:"
echo "    - none" 

echo "- name: Venus"
echo "  radius: 6052"
echo "  satellites:"
echo "    - none" 

echo "- name: Earth"
echo "  radius: 6371"
echo "  satellites:"
echo "    - Moon" 

echo "- name: Mars"
echo "  radius: 3396"
echo "  satellites:"
echo "    - Phobos" 
echo "    - Deimos" 
#include 

int main() 
{
    // in-line YAML
    char *mercury = "{name: Mercury, radius: 2440, satellites: [none]}";
    char *venus = "{name: Venus, radius: 6052, satellites: [none]}";
    char *earth = "{name: Earth, radius: 6371, satellites: [Moon]}";
    char *mars = "{name: Mars, radius: 3396, satellites: [Phobos, Deimos]}";
	
    printf("--- [%s, %s, %s, %s]", mercury, venus, earth, mars);
	
    return 0;
}

The examples above produce the following text format result:

name: Mercury
radius: 2440
satellites: 
none
name: Venus
radius: 6052
satellites: 
none
name: Earth
radius: 6371
satellites: 
Moon
name: Mars
radius: 3396
satellites: 
Phobos
Deimos

Generate a Result Using the Task Controller

Some languages implement a task controller that can take a native script structure and format it as a YAML string. This formatted string is then printed to stdout as normal. The advantage of using the controller is that the complex result can be constructed using native script objects without having to consider YAML at all. The task controller object is provided by the language plug-in and normally features a printObject method that prints its argument as YAML.

The Usage document listed in the Resource Browser details how to access the task controller for each applicable language. The following examples use a task controller to generate a complex result:

import java.util.HashMap;
import java.util.ArrayList;
import com.mugginsoft.KosmicTaskController;

class kosmicTask
{ 
    public static void main(String args[])
    {
        String name = "name";
        String radius = "radius";
        String satellites = "satellites";
        
        // Mercury
        HashMap Mercury = new HashMap();
        String moonsMercury[] = {"none"};
        Mercury.put(name, "Mercury");
        Mercury.put(radius, 2440);
        Mercury.put(satellites, moonsMercury);

        // Venus
        HashMap Venus = new HashMap();
        String moonsVenus[] = {"none"};
        Venus.put(name, "Venus");
        Venus.put(radius, 6052);
        Venus.put(satellites, moonsVenus);

        // Earth
        HashMap Earth = new HashMap();
        String moonsEarth[] = {"moon"};
        Earth.put(name, "Earth");
        Earth.put(radius, 6371);
        Earth.put(satellites, moonsEarth);

        // Mars
        HashMap Mars = new HashMap();
        String moonsMars[] = {"Phobos", "Deimos"};
        Mars.put(name, "Mars");
        Mars.put(radius, 6396);
        Mars.put(satellites, moonsMars);

 
        // build dynamic array of planets
        ArrayList planets = new ArrayList();
        
        planets.add(Mercury);
        planets.add(Venus);
        planets.add(Earth);
        planets.add(Mars);
    
        // print native object as YAML
        KosmicTaskController.printObject(planets);
    }
}
require_once "KosmicTaskController.php";

$name = 'name';
$radius = 'radius';
$satellites = 'satellites';

# Mercury
$moons = array("none");
$Mercury  = array($name => "Mercury", $radius => 2440, $satellites => $moons);

# Venus
$moons = array("none");
$Venus  = array($name => "Venus", $radius => 6052, $satellites => $moons);

# Earth
$moons = array("moon");
$Earth  = array($name => "Earth", $radius => 6371, $satellites => $moons);	

# Mars
$moons = array("Phobos", "Deimos");
$Mars  = array($name => "Mars", $radius => 3396, $satellites => $moons);

# define planets array
$planets[] = $Mercury;
$planets[] = $Venus;
$planets[] = $Earth;
$planets[] = $Mars;

# print native object as YAML
KosmicTaskController::printObject($planets);

Return a Native Object as the Result

Some language plug-ins, notably the Cocoa framework bridges, can return native script objects directly as results. This is possible because in each case the bridge converts the native script object into a Cocoa representation that KosmicTask can manipulate directly.

The following examples illustrate how to return a native script object as a result:

[    
    mercury := #{'name' -> 'Mercury', 'radius' -> 2440, 'satellites' -> {'none'}}. 
    venus := #{'name' -> 'Venus', 'radius' -> 6052, 'satellites' -> {'none'}}.
    earth := #{'name' -> 'Earth', 'radius' -> 6371, 'satellites' -> {'Moon'}}.
    mars := #{'name' -> 'Mars', 'radius' -> 3396, 'satellites' -> {'Phobos', 'Deimos'}}.

    " planets array "
    planets := {}.
    planets add:mercury.
    planets add:venus.
    planets add:earth.
    planets add:mars.
    
    " return planets "
    planets
]
def kosmictask()

    mercury =  {:name => "Mercury", :radius => 2440, :satellites => ['none']}
    venus =  {:name => "Venus", :radius => 6052, :satellites => ['none']}
    earth =  {:name => "Earth", :radius => 6371, :satellites => ['Moon']}
    mars =  {:name => "Mars", :radius => 3396, :satellites => ['Phobos', 'Deimos']}
	
    return [mercury, venus, earth, mars]
end

Application Result Keys

KosmicTask defines a number of application keys that be used to identify particular parts of a dictionary result. Whenever a complex result is generated KosmicTask scans the result for any application keys and processes the identified parts of the result accordingly. The application keys therefore act as tags that enable KosmicTask to actively interpret and process the result.

The following application keys can be returned as part of a complex result:

kosmicData
The data key identifies an item as containing result data. This is used to identify the main body of the result when other application keys are present.
kosmicError
The error key identifies the associated item as an error value.
kosmicFile
The file key identifies an item or items as files to be included as part of the result.
kosmicInfo
The info key identifies an item as containing an informational message.
kosmicName
The name key identifies the result.
kosmicStyle
The style key defines the CSS styles to be applied to an associated item identified by a data key.

When a complex result is displayed in document view its various parts are displayed on the following order:

  • kosmicName
  • kosmicData
  • kosmicInfo
  • kosmicError

This ordering ensures that the result components are presented in a clear and coherent manner.

Complex Result Examples

The application keys are named in such a way that they should not clash with user defined key names. When KosmicTask scans a result for matching application keys it does so in a case insensitive fashion. The following examples generate complex results containing various application keys:

echo "--- {kosmicData: Save the blue planet, kosmicStyle: 'color:blue;'}"
on KosmicTask()
    try
        -- return a list
        set myResult to {"Save the blue planet", "Hubert Muggins will assist"}
        
        -- set style string
        set myStyle to "color:blue;font-weight:bold;font-style:italic;text-decoration:underline;font-size:18pt;"
        
        -- return result record
        return {kosmicData:myResult, KosmicStyle:myStyle}
        
    on error errorMessage number errorNumber
        return {kosmicError:errorMessage}
    end try
    
end KosmicTask
require 'osx/cocoa'

# KosmicTask controller
$taskController = OSX.NSClassFromString("KosmicTaskController")

def kosmictask()

    # create path to temp result file from taskController.
    # this file will be automatically deleted when the task ends.
    path = $taskController.resultFileWithName_("capture.png");
    
    # capture sceen shot to file
    system "screencapture -t png " + path
    
    # create our result hash
    result = Hash.new()
	
    # add keyed file path
    result[:kosmicFile] = path

    # add keyed info
    result[:kosmicInfo] = "file returned"
		
   return result
end