Argonaut is a script library for parsing command-line arguments to AppleScript/ASObjC scripts. The library provides handlers for specifying arguments and their requirements, parsing arguments at runtime, performing type checking, and running callbacks when specified conditions are met. Argonaut is a high-level framework for argument specification and handling that abstracts away many of the finer implementation details so that you can focus on creating useful command-line scripts.
Installation
Download and unzip Argonaut.zip from https://github.com/SKaplanOfficial/Argonaut/releases/latest. Then, move or copy Argonaut.scptd into your ~/Library/Script Libraries directory. You'll then be able to use Argonaut in future scripts, and you can view the scripting dictionary in Script Editor or Script Debugger just as you would any other.
Usage
To begin, include the library in a script using the statement use script "Argonaut" version "1.0"
This will allow you to use terminology from Argonaut in the rest of the script.
The overall process in working with Argonaut is summarized as:
- Add named arguments using the
add argument
command, specifying as much or as little additional information as you need.
- Run the
initialize argument parser
command, optionally providing a parser configuration
record to customize how the parser behaves and add additional information to your script's help text.
- Define handlers to run when specific conditions are met, e.g. when all arguments are valid or when no arguments yield errors, and connect them to the parser using the
handle arguments
command.
- Run the script from the command-line using osascript, providing arguments that fit your specifications.
Adding Arguments
Every argument has a unique name associated with it; all other properties are optional. Properties are interwoven such that using different values for the type
, for example, influences how validator
handlers are applied, and most properties have some impact on how the help text
displays.
When running a script from the command-line, arguments are primarily specified by either their full flag (--name) or a shorthand flag (-x) if you define one. Shorthand flags are not automatically derived from the name as you might have multiple arguments beginning with the same letter. Thus, you can specify a custom shorthand flag using add argument "myArg" flag "x"
, which will register -x as a valid alternate indicator. The value you want to pass in for myArg would come after -x, e.g.: osascript example.scpt -x "value"
.
By default, arguments accept a single (non-list) value of any type. To enforce a specific data type on the argument's value, specify a type using add argument "myArg" type [type]
. The type can be a standard AppleScript class, such as integer
or URL
, or it can be one of the Argonaut-specific types such as ArgInteger
, ArgPath
, or ArgURLList
. Singular value types will look for a single value immediately following a flag, while list types will match every value up until the next flag occurs or the end of the line.
When users invoke the top-level --help or -h flag on the script, in addition to displaying the global help text
, the help text
for each argument will be displayed. Users can get more detail about specific arguments by passing "help" as the value, regardless of the argument's data type, which will print out the argument's details
.
You can specify dependencies
for an argument to require that other arguments are also provided whenever the argument is used. These can be specified as either a list of argument names or a list of argument
records. Failing to supply each dependency argument will yield an error.
Validation Handlers (Custom Validators)
Argonaut automatically handles value type validation for each of the built-in argument types, but, if you need to verify other kinds of inputs, you can create a custom handler and provide it as the validator
parameter when creating a new argument. The handler must accept two parameters: 1) the name of the argument and 2) the string value. The handler must return a record
with fields for the validity
of the argument and the augmented value
. The validity
must be one of the argument state
constants.
As an example, consider a script that displays an standard alert given a title, message, and type provided as arguments. Any arbitrary string of text will suffice for the title and message, so both can use the type any
or ArgAny
(the default). The alert type, however, has to map to one of the AppleScript alert type constants (critical/informational/warning). We can use a custom validation handler to address this as follows:
use script "Argonaut" version "1.0"
use scripting additions
on isAlertType(theArg, value)
set isValid to invalid
set augmentedValue to missing value
if value is "critical" then
set isValid to valid
set augmentedValue to critical
else if value is "informational" then
set isValid to valid
set augmentedValue to informational
else if value is "warning" then
set isValid to valid
set augmentedValue to warning
end if
return {validity:isValid, value:augmentedValue}
end isAlertType
on run argv
add argument "title" help text "The title text of the alert." with required
add argument "message" help text "The message text of the alert." without required
add argument "type" help text "The alert type." validator isAlertType details "Must be one of: 'critical', 'informational', or 'warning'." without required
initialize argument parser
handle arguments argv
end run
In place of a handler, you can instead supply a script object which defines a validate(theArg, value)
handler within it. The advantage to this is that you'll be able to access property local to your script. The script above is equivalent to:
use script "Argonaut" version "1.0"
use scripting additions
property importantProperty : "important data"
script AlertTypeValidator
on validate(theArg, value)
log importantProperty
...
end validate
end script
on run argv
...
add argument "type" help text "The alert type." validator AlertTypeValidator details "Must be one of: 'critical', 'informational', or 'warning'." without required
...
end run
Action Handlers
Similar to validators, you can also supply a handler or script object to specify an action to run when parsing has completed for any given argument. The action runs regardless of whether the value is valid and regardless of whether the argument exists in the input; you will have to handle these conditions in your implementation however you see fit. Both the handler and script object variations must support three parameters: the argument itself, its status, and its value (correctly typed). In the script object, the handler must be named runAction
. The example below showcases both variations.
use script "Argonaut" version "1.0"
property importantProperty : false
script ActionRunner
on runAction(theArg, status, value)
log class of value
log importantProperty -- Will work
end runAction
end script
on runAction(theArg, status, value)
log theArg
log importantProperty -- Won't work property
end runAction
on run argv
add argument "arg1" type ArgInteger action ActionRunner without required
add argument "arg2" type ArgFlag action runAction without required
initialize argument parser
handle arguments argv
end run
Handling Parsed Values
When you use the handle arguments
command, you can supply handlers for several conditions at once. Each handler will be called with the list of arguments passing the condition alongside the summary record of all arguments and values. The value returned by the last handler run (the last one passed to the command) will be returned as the overall result of the command.
If you don't want to use the handle arguments
command, you can call check arguments
directly and then access arguments and their values with the list arguments
command. You will have to filter arguments manually or using filter arguments
.
Filtering Arguments
If you find yourself needing to filter arguments beyond the basics handled by handle arguments
, you can use filter arguments
. This command accepts several parameters for specifying the criteria to filter arguments by, and it accepts a using custom filter
parameter for even more granular control.
All of the following are valid calls to filter arguments
:
filter arguments by state valid -- Gets all arguments passed to the script that have a valid value
filter arguments by type ArgList -- Gets all arguments accepting any kind of list as a value
filter arguments (list arguments) by type {ArgPath, ArgFlag} -- Gets arguments that are either flags or accept a path value
filter arguments with required -- Gets all required arguments
filter arguments without required -- Gets all optional arguments
filter arguments with has value -- Gets all arguments that have some value specified (even if it is invalid)
filter arguments using custom filter passesTest -- Gets arguments for which the passesTest handler returns true
filter arguments using custom filter MyCustomFilter -- Gets arguments for which the passesTest handler of the MyCustomFilter script object returns true
filter arguments by state valid by type ArgURL -- Gets all arguments whose value is a valid URL
filter arguments by state excluded with value -- Gets all arguments that aren't directly specified but have a default value
Other Notes
-
Argonaut will attempt to convert argument values to their configured type before calling any custom handlers for validation, actions, or result handling. For example, file paths supplied as text strings will be converts to instances of AppleScript's
POSIX file
class.
-
Arguments' status property has a missing value until there are validated either automatically by
handle arguments
or manually using check arguments
or check for argument
.