How to launch specific task from input variable in VS Code? - visual-studio-code

I'm trying to create a launch configuration where an environment variable is dynamically determined by a shell script. Even though a command variable can start a task via workbench.action.tasks.runTask, it doesn't seem to be possible to specify which task to run. Input variables seem to be a little more flexible in that regard, but I can't seem to get it to work. Here is what I got:
launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": []
}
],
"inputs": [
{
"type": "command",
"id": "foo",
"command": "workbench.action.tasks.runTask",
"args": {
"args": "bar",
}
}
]
}
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "bar",
"type": "shell",
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1"
}
]
}
The issue is that the user is still queried for which task to run. I'm most insecure about the inputs.args section of the launch.json. I don't really know what the key value should be. Perhaps the implementation helps to figure this out?

This answer not really relates to make use of a vscode task, but your introducting sentence offers the motivation/what is intended to be solved.
I was faced to the same question and was wondering about vscode's input type:command. It offers a way to embed a (custom) vscode command -- which looks like a powerfull mechanism to embed a (custom) extension here. But I didn't found a builtin command that simply executes a shell script and returns it stdout. Thus an extension to capture the output of a shell command is imho required todo the trick.
E.g. https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input
provides a command shellCommand.execute doing exactly this.
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": []
}
],
"inputs": [
{
"id": "foo",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1",
"cwd": "${workspaceFolder}",
/* To prevent user from selecting output (if there is just
one line printed by command), un-comment next line */
//"useSingleResult": true
}
}
]
}
(Inspired by https://stackoverflow.com/a/58930746/1903441)

In your launch.json, try replacing
"args": {
"args": "bar",
}
with
"args": "bar"

It seems that in vscode, you cannot pass a return or even an environment variable from task.json to launch.json. But you can use a file as a intermediate.
For example, in task.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "bar",
"type": "shell",
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1 > ${workspaceFolder}/.vscode/temp"
}
]
}
In launch.json you set bar as preLaunchTask, and later access the file using inputs, like this:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": [],
"preLaunchTask": "bar",
}
],
"inputs": [
{
"id": "foo",
"type": "command",
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/.vscode/temp",
}
}
]
}
To get the comment working, just install this extension: https://marketplace.visualstudio.com/items?itemName=rioj7.command-variable

Related

How to perform operations on VSCode macros?

My launch.json specifies a list of arguments for a given debug session (For airflow debugging in this case):
{
"version": "0.2.0",
"configurations": [
{
"name": "airflow_debug",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/.venv/bin/airflow",
"preLaunchTask": "activate-python-venv",
"console": "integratedTerminal",
"env": {
"AIRFLOW_HOME": "${workspaceFolder}",
"AIRFLOW__CORE__LOAD_EXAMPLES": "False",
"AIRFLOW__CORE__DAGS_FOLDER": "${workspaceFolder}/dags",
"AIRFLOW__CORE__EXECUTOR": "SequentialExecutor",
"PYTHONPATH": "${workspaceFolder}/plugins:${workspaceFolder}/dags:${env:PYTHONPATH}"
},
"args": [
"dags",
"test",
"migrate_dtm",
"2022-11-24"
]
}
]
}
In order to be able to debug my dags, I must specify the dag name in the args, here it is migrate_dtm. A more sophisticated way, would be to deduce the name of the dag from the name of the file My file's name is migrate_dtm_dag.py.
The goal here is not to change the launch.json and manually specify the dag name within every different debug launch; but only set a nomenclature rule for the devs to follow.
Something like this would help
"args":[
...
"${file.split('/')[-1].split('_dag')'}", // First split to get only the file name without the path, second split to extract the dag name.
...
]
Is there a way to achieve something like this in a VSCode macro? Or to perform operations on macros at all?
you can use the extension Command Variable
{
"version": "0.2.0",
"configurations": [
{
"name": "airflow_debug",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/.venv/bin/airflow",
"preLaunchTask": "activate-python-venv",
"console": "integratedTerminal",
"env": {
"AIRFLOW_HOME": "${workspaceFolder}",
"AIRFLOW__CORE__LOAD_EXAMPLES": "False",
"AIRFLOW__CORE__DAGS_FOLDER": "${workspaceFolder}/dags",
"AIRFLOW__CORE__EXECUTOR": "SequentialExecutor",
"PYTHONPATH": "${workspaceFolder}/plugins:${workspaceFolder}/dags:${env:PYTHONPATH}"
},
"args": [
"dags",
"test",
"${input:getdag}",
"2022-11-24"
]
}
],
"inputs": [
{
"id": "getdag",
"type": "command",
"command": "extension.commandvariable.transform",
"args": {
"text": "${fileBasenameNoExtension}",
"find": "_dag"
}
}
]
}
The default replace is "", so it removed the text _dag.
With the command extension.commandvariable.dateTime you can create a date string for today.

Nesting/joining a workspace input variable inside multi folder workspaceFolder variable?

Is there a way to nest an input variable inside other variables, particularly ${workspaceFolder}? As an example .code-workspace file:
{
"folders": [
{
"name": "Client",
"path": "path/to/client/code"
},
{
"name": "Server",
"path": "path/to/server/code"
},
{
"name": "Shared",
"path": "path/to/shared/code"
}
],
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "apphere"
}
],
"inputs": [
{
"id": "pickProject",
"type": "pickString",
"description": "Select a project:",
"options": [
"Client",
"Server"
]
}
]
}
}
All projects (Client and Server in this example) would share the same launch configurations, the only thing that would need to change is the cwd value. Unfortunately you cannot use ${workspaceFolder} directly in a multi folder workspace as you receive this error:
Variable ${workspaceFolder} can not be resolved in a multi folder workspace. Scope this variable using ':' and a workspace folder name.
What would be perfect is being able to do something like this:
"cwd": "${workspaceFolder:${input:pickProject}}"
Unfortunately this does not work. Is there another way to provide a dynamic scope for the workspaceFolder variable?
I did figure out one rather hacky way to handle this although it feels like there should be a better way: If you change the pickString input options to the folder paths and then change the debug cwd to "cwd": "${workspaceFolder:Shared}/../../../${input:pickProject}" you can arbitrarily pick one of the folders, traverse back out to the root workspace directory, and then append the ${input:pickProject} variable onto the end. In addition to the directory traversals, the debug choices you see will be "path/to/client/code" and "path/to/server/code" instead of the more clean "Client" and "Server". But at least it does seem to work, albeit not overly ideal.
With the extension Command Variable you have possible solutions
extension.commandvariable.file.fileAsKey
When you have a file open and current for Client or Server the F5 will select the correct cwd based on the path of the current file.
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"cwd": "${input:getCWD}",
"program": "apphere"
}
],
"inputs": [
{
"id": "getCWD",
"type": "command",
"command": "extension.commandvariable.file.fileAsKey",
"args": {
"/client/": "/path/to/client/code",
"/server/": "/path/to/server/code"
}
}
]
}
extension.commandvariable.pickStringRemember
If you want a pick list that shows Client and Server but returns the corresponding paths use:
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"cwd": "${input:pickPath}",
"program": "apphere"
}
],
"inputs": [
{
"id": "pickPath",
"type": "command",
"command": "extension.commandvariable.pickStringRemember",
"args": {
"description": "Select a project:",
"options": [
["Client", "/path/to/client/code"],
["Server", "/path/to/server/code"]
]
}
}
]
}

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

Pass arguments to command in visual studio code

Is it possible to run a command in a variable and pass parameters? Given that this command requires input arguments.
Example:
// in launch.json
{
"program": "${command:somecommand(foo=${someargument})}"
}
Create an input in your launch.json which calls your command, there you can pass your argument. You can then reference the input in your attach/launch config.
// launch.json
{
"version": "0.2.0",
"inputs": [
{
"id": "commandInput",
"type": "command",
"command": "somecommand",
"args": {
"foo": "${someargument}"
}
}
],
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${input:commandInput}"
}
]
}

How to run a command in Visual Studio Code with launch.json

Is there a way to execute an ssh command when debugging a project with .vscode/launch.json?
For example: ssh -i xxxxx.
Or is it possible to create a command that you can run from the F1 command palette pop-up? Something like RunCustomCommandxx.
You can define a task in your tasks.json file and specify that as the preLaunchTask in your launch.json and the task will be executed before debugging begins.
Example:
In tasks.json:
For version 0.1.0:
{
"version": "0.1.0",
"tasks": [{
"taskName": "echotest",
"command": "echo", // Could be any other shell command
"args": ["test"],
"isShellCommand": true
}]
}
For version 2.0.0 (newer and recommended):
{
"version": "2.0.0",
"tasks": [{
"label": "echotest",
"command": "echo", // Could be any other shell command
"args": ["test"],
"type": "shell"
}]
}
In launch.json:
{
"configurations": [
{
// ...
"preLaunchTask": "echotest", // The name of the task defined above
// ...
}
]
}
Tasks documentation: https://code.visualstudio.com/docs/editor/tasks
Launch configuration: https://code.visualstudio.com/docs/editor/debugging#_launch-configurations
The format changed. Visual Studio Code can create the tasks.json file for you. Inside your launch.json file and inside any configurations object, just define preLaunchTask to force auto-creation of the tasks.json template file:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "launch program",
"skipFiles": [ "<node_internals>/**"],
"preLaunchTask": "myShellCommand",
"program": "${workspaceFolder}/test.js"
}
]
}
If you do not have file tasks.json configured:
launch the debugger. Visual Studio Code will inform you: "could not find the task
myShellCommand"
select Configure Task → Create tasks.json file
from template → Others
Your tasks.json template file will then be created for you. Add your command to command and the name you put in preLaunchTask to label:
{
"version": "2.0.0",
"tasks": [
{
"label": "myShellCommand",
"type": "shell",
"command": "echo goodfood"
}
]
}
For me, I just needed an environment variable, which is different. You don't want a task for this because (at least for me) it doesn't work when the launcher is run.
Thanks to here, I got it working like this, inside my launcher (launch.json) entry:
"environment": [{
"name": "ENVIRONMENT_VARIABLE_NAME",
"value": "${workspaceFolder}/lib" //Set to whatever value you want.
}],
My version of the configuration allows to just run a defined task and carried on (in my case, the task is to run the currently open Groovy file):
"configurations": [
{
"name": "Launch groovy",
"request": "launch",
"type": "coreclr",
"preLaunchTask": "groovy",
"program": "cmd.exe",
"args": ["/c"],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"internalConsoleOptions": "neverOpen"
}
]
And the task:
"tasks": [
{
"label": "groovy",
"type": "shell",
"command": "groovy ${file}"
}
]
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch app",
"program": "lib/main.dart",
"request": "launch",
"type": "dart"
},
{
"name": "Build an APK Release",
"command": "flutter build apk --release",
"request": "launch",
"type": "node-terminal"
},
{
"name": "Install an APK on a device",
"command": "flutter install",
"request": "launch",
"type": "node-terminal"
}
]
}
for flutter developers who is searching how to run flutter build commands.
in tasks.json add
"tasks": [
{
"type": "flutter",
"command": "flutter",
"args": [
"pub",
"run",
"build_runner",
"build",
"--delete-conflicting-outputs"
],
"problemMatcher": [
"$dart-build_runner"
],
"group": "build",
"label": "flutter: flutter pub run build_runner build --delete-conflicting-outputs"
},
]
then from vscode you can try "run task" it will show you flutter: flutter pub run build_runner build --delete-conflicting-outputs
this way you don't need to memorize and type to terminal source code generation/build commands