Tasks

Nova’s Tasks system offer users a freeform, highly-configurable way of running external operations from within the IDE.

The simplest way of using Tasks is by adding a simple “Custom Script” task configuration that is always available from a user’s project settings. This allows the user to define a script that will execute either on the local machine or a remote server when the configuration is run, forwarding its output to an IDE output report.

Extensions can extend this idea further in two ways:

Defining a Task Template

Defining a Task template in your extension adds a new item to the project settings “Add Task” interface of a user’s Project Settings. This allows a user to instantiate your template as one or more new configurations within their project. Each configuration added references the template in your extension for configuration options, allowing the extension to evolve without the need to recreate configurations.

Templates are great for defining a user-customizable task that should persist with their project and is not necessarily reliant on other configuration files within the project.

A template defines what command is executed when the user runs a configuration created from it, along with the arguments it is passed. Arguments are defined a way that allows them to be edited by a user in the configuration editor, much like an extension’s preferences.

The extension’s extension.json can include a taskTemplates object defining the templates that are exposed by the extension.

Each item in the object is keyed by the template’s identifier, which should not change once an extension is released: Configurations created from it reference this identifier to determine how the configuration is executed.

The value of each item is an object defining how the template behaves.

Here is an example of a configuration which executes a local PHP development web server:

"taskTemplates": {
    "webserver": {
        "name": "PHP Webserver",
        "description": "Runs the PHP development server.",
        "persistent": true,
        "tasks": {
            "run": {
                "shell": true,
                "command": "php",
                "args": [
                    "-S", "$(Config:php.host):$(Config:php.port)",
                    "-t", "$(Config:php.document-root)",
                    "$(Config:php.custom-args)"
                ],
                "env": {
                }
            }
        },
        "config": [
            {
                "key": "php.host",
                "title": "Host",
                "type": "string",
                "placeholder": "localhost",
                "default": "localhost"
            },
            {
                "key": "php.port",
                "title": "Port",
                "type": "number",
                "placeholder": "8000",
                "default": 8000,
                "min": 1,
                "max": 65535
            },
            {
                "key": "php.document-root",
                "title": "Document Root",
                "type": "path",
                "default": "."
            },
            {
                "key": "php.custom-args",
                "title": "Additional Arguments",
                "description": "Custom arguments to pass to the PHP webserver command.",
                "type": "string"
            }
        ]
    }
}

Task Actions

The most important details of a template are defined in its tasks section. This object maps each action, by name, to an object that defines how and what process should be invoked.

Available actions are: build, run, clean.

Value Description Notes
command The executable command to invoke
shell If true, the command will be executed within a shell
args An array of interpolated strings passed to the command
env Interpolated environment variables set for the command
matchers An array of Issue Matcher identifiers used to automatically parse task output.
resolve A string representing a task assistant identifier used to resolve the action. Added in Nova 5.
data Arbitrary data that may be provided when resolving the action. Added in Nova 5.
buildBeforeRunning If set to true, then the Run action will automatically invoke Build before it.
persistent If set to true, then the action will use UI elements that denote it is persistent (an action that will run for a protracted length of time, such as a preview server).

The command value is the executable name that will be invoked by the IDE. This may be a path to a script, relative to the extension root (such as Scripts/run.sh), or a command available on the user’s PATH.

For most cases, be careful when specifying paths for the command. If the path is not valid on all user’s computers it can cause the run to fail. Use absolute paths when the expectation is that the tool being invoked is required to be at this location. Otherwise, use a singular command name allowing it to be resolved against the extension’s container, or use the shell parameter allowing it to be interpreted against the user’s PATH.

If the action to be invoked is not known when the task template is defined, a template may use the resolve value to specify a Task Assistant identifier that can resolve the task. When the action is invoked, the assistant’s resolveTaskAction() method will be invoked to request an action instance, such as TaskProcessAction. If the data property is provided, the JSON object it specifies will be set for the context parameter’s data property during resolution.

Note: In previous versions of Nova (before Nova 2), the tasks value was instead a singular task value that could only specify one task action (for Run). This was amended to support multiple actions.

Variables

String values provided in an action template’s args and env properties can be interpolated using the Snippets format, meaning the values may contain special string substitutions that are resolved at runtime. These substitutions follow a similar format to shell substitutions: $VariableName for singular variables, and ${Expression} for more complex expressions. The former is simply a shorthand subset of the latter which can only contain alphanumeric characters and the underscore. The variables and expressions available include those listed below.

Named Variables
Configuration Variables

String substitution may reference values stored in the user’s global and project configuration using an expression of the form ${Config:my.config-key}, where my.config-key is a key for a configuration item. Expressions of this form will check the most specific configuration available first, falling back if no value is found.

The order of precedence for configurations is:

If no value is found within a configuration, the default will be returned (if one is defined) before moving on to the next context. If no value is found, an empty string will be substituted.

Command Variables

For more complex handling of substitution, an extension Command may be invoked. This command need not be defined in an extension’s visible commands object in its extension.json file, it only needs to be registered with the extension’s CommandsRegistry.

Commands may be invoked by using an expression of the form ${Command:my.command-name}, where my.command-name is the name of the command used to register with the nova.commands.add() of the commands registry. The command will then be invoked asynchronously by the extension runtime. If it returns a Promise object, the runtime will wait for the promise to resolve before performing the string substitution, unless the task requesting it is cancelled before the promise resolves.

Configuration

Each template may define a config section, which uses the same format as Preferences items. These configuration items may be referenced in the string substitution of arguments and environment passed to the template’s executable using the format $(Config:my.config-key). The value will be checked against those set for the configuration, as well as the user’s project and global preferences.

Deprecation

If a task template should be replaced with another, or removed entirely, an extension may optionally declare it as deprecated for any amount of time needed to inform the user that the template will be replaced or removed.

To specify a task template as deprecated, use the deprecated property on the template object. The value of this property may be:

The deprecation notice will be shown in the task template’s edit pane of the project settings.

"taskTemplates": {
    "webserver": {
        "name": "PHP Webserver",
        "description": "Runs the PHP development server.",
        "deprecated": "Consider using the other thing instead."
        "tasks": {...}
    }
}

Defining a Task Assistant

Added in Nova 2.

In many cases, requiring a user to add an instance of a task via a Task Template may be too much overhead. If the task in question is defined by existing files or metadata in the project and can be detected by an extension, a simpler option may be to contribute a Task Assistant.

A Task Assistant is a JavaScript object that is registered with the AssistantRegistry. It allows an extension to dynamically construct and return task objects to be displayed in the IDE interface and invoked by the user.

For more information, see the AssistantRegistry and Task classes.

For tasks that may change over time (such as in response to a user updating a configuration file, or changing configuration values in the extension), an extension may invoke the reloadTasks(identifier) method on the global Workspace object.