VsCode : How to generate custom task input options from a command? - visual-studio-code

Let's say we have the following custom task :
{
"version": "2.0.0",
"tasks": [
{
"label": "do smthg",
"type": "shell",
"command": "echo \"selected option: ${input:option_name}\"",
"problemMatcher": [],
"presentation": {
"panel": "dedicated",
"focus": true
}
}
],
"inputs": [
{
"type": "pickString",
"id": "option_name",
"description": "select an option :",
"options": [
// want possible options to be the output of a command
],
"default": ""
}
]
}
But I want the available options to be the result of a command,
like ls, or a cat smthg.txt | grep -oP '\"value\:\"\K\w*',
how can I do that ? Is it only possible ?

You can use the extension Command Variable v1.34.0
Use the replacement for pickString named extension.commandvariable.pickStringRemember.
This command can read options from a file, you determine the format with a regexp like the problem matcher of tasks.
An example:
"inputs": [
{
"type": "command",
"id": "option_name",
"command": "extension.commandvariable.pickStringRemember",
"args": {
"description": "select an option :",
"options": [
["always 1", "5000"],
["always 2", "5100"]
],
"default": "",
"fileName": "${workspaceFolder}/foo-bar.txt",
"pattern": {
"regexp": "^\\s*(?!#)([^=]+?)\\s*=\\s*(?:(\\{.+\\})|(.+))$",
"label": "$1",
"json": "$2",
"value": "$3"
}
}
}
]
If you don't have label - value lines you can simplify the pattern to
"pattern": {
"regexp": "^\\s*(?!#)(.+)$"
}
If you don't have static options (always 1/2 in example) you can remove the options property from args.
With an additional task you create the file with a command or a shell script if grep-ping and file redirection might be a problem (pass the output file name, using variables, as argument to the script).
You can construct a sequence of tasks, a compound task, see VSC doc.

Related

In tasks.json in vscode, Is it possible to reference single elements in an array defined in settings.json?

When writing an extension in vsCode, is it possible to create a configuration (a field in my settings.json) where I can store multiple values and configure an actively selected one?
Say I have an external dependency, which I need to reference in my tasks.json. Through the configuration contribution point of the extension i can provide the following property:
"myextension.dependencyDir": {
"scope": "resource",
"type": "string",
"description": "Path to the external dependency"
}
I can now reference this path in my tasks.json through ${config:myextension.dependencyDir}
However, lets say my dependency comes in various versions, which I would like to switch from the comfort of my settings(UI)
I know that by using an array I can store multiple versions of the dependency.
"myextension.dependencyDir": {
"scope": "resource",
"type": "array",
"items": {
"type": "string"
},
"description": "Path to the external dependency"
},
However, I cannot seem to reference single elements out of this array from my tasks.json.
By calling ${config:myextension.dependencyDir} now, i get the entire array.
I have tried to call
${config:myextension.dependencyDir[0]}
${config:myextension.dependencyDir(0)}
${config:myextension.dependencyDir:0}
... and many other variations
to query the first item in my array. Neigther of those attempts have worked.
${config:myextension.dependencyDir}[0] just appends '[0]' to the
last element.
I know that I can create custom objects and configure them in my settings.
"myextension.dependencyDir": {
"scope": "resource",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of your dependency version"
},
"value": {
"type": "string",
"description": "Path to the specific Dependency version"
}
}
},
"description": "Path to the external dependency"
},
However, just like before, I don't know how to access a single entry in my array, let alone adress the specific fields name and value.
Is what I am trying to do possible? Is it even the proper way of doing this? Does anyone have a solution to my problem or suggestions for a different approach?
Thanks in advance
BioZons
You can use the extension Command Variable v1.30.0
It has a command extension.commandvariable.config.expression. It allows to apply a JavaScript expression to the value of a configuration variable.
If the config variable is an array:
{
"version": "2.0.0",
"tasks": [
{
"label": "echo config var",
"type": "shell",
"command": "echo",
"args": [
"ConfigArray: ${input:configArray}",
],
"problemMatcher": []
}
],
"inputs": [
{
"id": "configArray",
"type": "command",
"command": "extension.commandvariable.config.expression",
"args": {
"configVariable": "myextension.dependencyDir",
"expression": "content[1]"
}
}
]
}
If the config variable is an array and you want to pick the array element:
{
"version": "2.0.0",
"tasks": [
{
"label": "echo config var",
"type": "shell",
"command": "echo",
"args": [
"ConfigArrayPick: ${input:configArrayPick}",
],
"problemMatcher": []
}
],
"inputs": [
{
"id": "configArrayPick",
"type": "command",
"command": "extension.commandvariable.config.expression",
"args": {
"configVariable": "myextension.dependencyDir",
"expression": "content[${pickStringRemember:serverNr}]",
"pickStringRemember": {
"serverNr": {
"description": "Which server to use?",
"options": [
["development", "0"],
["live", "1"]
]
}
}
}
}
]
}
If the config variable is an array of objects:
{
"version": "2.0.0",
"tasks": [
{
"label": "echo config var",
"type": "shell",
"command": "echo",
"args": [
"ConfigObject: ${input:configObject}",
],
"problemMatcher": []
}
],
"inputs": [
{
"id": "configObject",
"type": "command",
"command": "extension.commandvariable.config.expression",
"args": {
"configVariable": "myextension.dependencyDir",
"expression": "content[1].name"
}
}
]
}

how can I change the Predefined variables in vscode json file

for example:
when I run the tasks.json:
{
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo ${workspaceFolder}\\bulid\\${relativeFileDirname}\\${fileBasenameNoExtension}.exe"
}
],
"version": "2.0.0"
}
it print
C:\Users\***\OneDrive\***\CLion\bulid\CourseBook\0201_SqList\SqList-main.exe
because my filename was SqList-main.c.
But what I want is Sqlist.exe.
Can I do something to let it print?
C:\Users\***\OneDrive\***\CLion\bulid\CourseBook\0201_SqList\SqList.exe
I want a smart or auto method because I have many files to change.
tips: the .c file can not rename for some reason.
Using extension Command Variable v1.6.0 there is a command that can transform a number of variables.
For this case you have to modify task.json
{
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo ${workspaceFolder}\\build\\${relativeFileDirname}\\${input:noMain}.exe"
}
],
"inputs": [
{
"id": "noMain",
"type": "command",
"command": "extension.commandvariable.transform",
"args": {
"text": "${fileBasenameNoExtension}",
"find": "-main"
}
}
]
}
You can use any regular expression as find and define a replace string with capture group references ($1), and the flags to use to construct the regular expression.

Invoking a user defined input in tasks from extension

I have created an extension to extend the input features in the tasks configuration. I would like to know if it is possible in my extension that I interpret other inputs and call them.
How could I make inside my extension if I see a string in the arguments like ${input:myInput}, I'd like to fetch/invoke whatever the user configured for that input.
Example:
The first input configuration contains a config from my extension where it will run a cat and theoretically depends on a second input that the user will just choose one of the options. I'd like to know how to parse the ${input:myInput} and invoke it to substitute.
"inputs": [
{
"id": "inputTest",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "cat ${input:myInput}",
}
},
{
"id": "myInput",
"description": "Choose a file",
"type": "pickString",
"options": [
"file1.txt",
"file2.txt"
]
}
]
As far as I understand VSC will expand variables if the value is a string or an array of strings.
Make the args property an array of strings.
"inputs": [
{
"id": "inputTest",
"type": "command",
"command": "shellCommand.execute",
"args": ["cat", "${input:myInput}"]
},
{
"id": "myInput",
"description": "Choose a file",
"type": "pickString",
"options": [
"file1.txt",
"file2.txt"
]
}
]
You can add special syntax to the array elements if you want to pass extra options to the command. For example
"args": ["cat", "${input:myInput}", "--XX--", "option1", "option2"]

How to use the same input string across multiple chained tasks in vscode?

I have multiple tasks that depend on each other and that should all operate on the same folder.
My config looks something like this:
{
"version": "2.0.0",
"tasks": [
{
"label": "first task",
"type": "shell",
"command": "bash",
"args": ["do stuff in ${input:pickFolder}"],
"dependsOn": "second task"
},
{
"label": "second task",
"type": "shell",
"command": "bash",
"args": ["also do stuff in ${input:pickFolder}"]
}
],
"inputs": [
{
"type": "pickString",
"id": "pickFolder",
"options": ["path/to/folder", "path/to/other/folder"]
}
]
}
As you might imagine I want both tasks run in the same folder. Also, I don`t want to have to pick the folder twice. How can I do that?
You can use the extension Command Variable v0.9.
Use the commands:
extension.commandvariable.pickStringRemember
extension.commandvariable.rememberPick

Is it possible to pass arguments to a task in Visual Studio Code

Here's an example of my tasks.json:
{
"version": "0.1.0",
"tasks": [
{
"taskName": "test",
"suppressTaskName": true,
"command": "python",
"args": [
"tests/brewer_tests.py"
],
"isTestCommand": true
}
]
}
I can run this with shift+cmd+alt+b. I can also run it with alt+t, and choose it from the menu. Is it possible to pass additional arguments in that menu? e.g.
And you could build it into your task like so:
{
"version": "0.1.0",
"tasks": [
{
"taskName": "test",
"suppressTaskName": true,
"command": "python",
"args": [
"tests/brewer_tests.py",
$arg1 # would resolve to "ARG1"
],
"isTestCommand": true
}
]
}
Or something similar?
I used the solution from this answer until now, but since Visual Studio Code has now an official support for task prompts I will add it as an answer here.
In your tasks.json file, you add the key inputs next to your tasks. This key contains an array with all possible parameters. Note that not every task has to use all of these inputs.
All of these inputs have an id, which you will use to reference the input in your task.
Now, in the task you only need to add ${input:myInputId} whereever you need the parameter.
Example:
{
"version": "2.0.0",
"tasks": [
{
"label": "Echo param",
"type": "shell",
"command": "echo ${input:param1}",
"problemMatcher": []
},
{
"label": "Echo without param",
"type": "shell",
"command": "echo Hello",
"problemMatcher": []
},
],
"inputs": [
{
"id": "param1",
"description": "Param1:",
"default": "Hello",
"type": "promptString"
},
]
}
The task Echo param will open a prompt, which lets you input a string value and it will then print this value. The task Echo without param will simply print "Hello".
Here's what is working for me for now - using this to run a golang snippet with custom arguments.
If you add a keyboard mapping to this, the process is very straightforward.
So far tested this only under Windows - linux version is commented out for that reason
{
"label": "runwithargs",
"type": "shell",
"windows": {
"options": {
"shell": {
"executable": "powershell.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command"
]
}
},
"command": "",
"args": [
{ "value": "$cmdargs = read-host 'Enter command line arguments';", "quoting": "weak"},
{ "value": "go run ${file} $cmdargs", "quoting": "weak"}
]
},
/*"linux": {
"command": "echo 'Enter command line arguments: '; read cmdargs;",
"args": [ "go run ${file} $cmdargs" ]
},*/
"presentation": {
"panel": "dedicated",
"focus": true
}
}
Regarding Input variables, VSCode 1.43 (Feb. 2020) adds a new feature:
promptString Password Input
The "promptString" "input" type can have "password": true, which will cause the quick input that shows to obscure the typed content like a password.