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"
#includeint 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
