Tasks config for `store_true` action?

I’m working on a rust tasks template, and don’t know how to implement the store_true style task templates. It looks like:

"tasks": {
    "build": {
        "shell": true,
        "command": "cargo",
        "args": [
            "build",
            "?????" // ?
        ]
    }  
},
"config": [
    {
        "key": "cargo.release",
        "title": "Release",
        "type": "boolean",
        "default": false
    }
]

If users click the release checkbox, then the extension will run the command cargo build --release.

How can I implement it?

For tasks defined only in the JSON manifest, you can use variable substitution for configuration keys in the task’s arguments, like so:

"tasks": {
    "build": {
        "shell": true,
        "command": "cargo",
        "args": [
            "build",
            "--",
            "${Config:cargo.release}"
        ]
    }  
},

However, this may not be enough for what you are trying to do, as since this is a boolean value, it will resolve to the string value “true”, not “release”. Therefore, you have a couple of different options:

Option 1: Enum Configuration Types

You could change this checkbox into an enum configuration item, which lets you specify items with both a display name and value, where the value will be what is substituted when used in the substitutions above. You would do something like:

"config": [
    {
        "key": "cargo.release",
        "title": "Release",
        "type": "enum",
        "default": "build",
        "choices": [
            ["build", "Build"],
            ["release", "Release"]
        ]
    }
]

This would lead to either cargo build -- build or cargo build -- release. (I can’t say I know how Cargo works, so this may be incorrect syntax for the former).

Option 2: JavaScript Task Assistant

If this isn’t quite what is needed, you can instead opt to provide a JavaScript Assistant that will resolve the task instead. This allows you full control over doing the substitutions yourself in JavaScript instead of relying on the JSON’s simple string substitutions.

Using the resolve property of the task, you can specify that the task’s value should be resolved at invocation time instead of specified in the JSON manifest.

"tasks": {
    "build": {
        "resolve": "cargo"
    }  
},

This will cause Nova to search for a registered JavaScript Task Assistant named cargo when the task’s build action is invoked. In your main.js script, using the AssistantRegistry registerTaskAssistant() API, you can register an object that can provide the resolved task with much more control:

class CargoAssistant {
    resolveTaskAction(context) {
        let config = context.config;
        let isRelease = config.get("cargo.release", "boolean");
        
        let args = ["build"];
        if (isRelease) {
            args.push("--");
            args.push("release");
        }
        
        let action = new TaskProcessAction("cargo", {
            shell: true,
            args: args
        });
        
        return action;
    }
}

exports.activate = () => {
    let assistant = new CargoAssistant();
    
    nova.assistants.registerTaskAssistant(assistant, {
        identifier: "cargo",
        name: "Cargo"
    });
};

I hope this makes sense! I’m happy to answer any more questions about this, as I realize I just threw a ton of information at you.

2 Likes