Using a shell command as VSCode task variable value - visual-studio-code

I am trying to define a VSCode task in tasks.json that would adapt to the specific architecture where VSCode runs. To do this, I want to get the architecture as uname --m (e.g. "aarch64" or "amd64"). My goal is to interpolate the output of uname into an environment variable like so
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "cmake",
"args": [
"-DMYLIB_INCLUDE_DIR=$MYLIB/include",
"-DMYLIB_LIBRARY=$MYLIB/lib"
],
"options": {
"env": {
"MYLIB": "${workspaceFolder}/mylib/${command:get_arch}"
}
},
}
]
In my case, I will have architecture-specific versions of mylib under mylib/aarch64, mylib/amd64, etc.
My attempt so far as been to define a second get_arch task used in the environment definition of MYLIB, that simply runs uname.
{
"label": "get_arch",
"type": "shell",
"command": "uname --m"
}
Of course, this task is not a proper command and so it isn't detected by VSCode and my build task fails. I checked out the documentation on variable substition, but they don't mention if it's possible to substitute a shell command. I guess this would be possible from within an extension, but I want to keep things as simple as possible.

This extension provides a way to launch arbitrary shell commands as a VS Code command:
"tasks": [
{
"label": "test_arch",
"type": "shell",
"command": "echo",
"args": [
"${MYARCH}"
],
"options": {
"env": {
"MYARCH": "${input:get_arch}"
}
},
"problemMatcher": []
},
],
"inputs": [
{
"id": "get_arch",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "uname -m"
}
}
]
One disadvantage I discovered is that you have to press Enter once more when the result of the command is prompted in picker. Aside of this, this is the straightest way to implement what you want, and yet it can be utilized in many similar situations.
Alternatively, you can add pickString input with arch picker or create an extension that adds only single command GetArch.

If you don't want to press enter every time, you can add the option useFirstResult: true in the args section.

Related

How to pass arguments to a task in vscode that executes a snippet linked to a hotkey?

I have this working hotkey:
{
"key": "cmd+t",
"command": "editor.action.insertSnippet",
"args": {
"name": "TryCatch"
}
},
Which wraps the selected text into a tryCatch block, and adds the wanted logs and error reporting.
However, I want to link it with other sequence of either hotkeys or tasks.
I have this task in tasks.json, when when triggered in attempts to perform the above command, it prompts me for user input, because I can't figure out how to pass the name of the snippet as an argument, similar to what is done with hotKey binding configurations in example 1 above.
This is the task:
{
"label": "insertSnippet",
"command": "${command:editor.action.insertSnippet}",
"args": [
// "${name:TryCatch}",
],
},
I've been trying to get tasks to execute without having to wait for user input or pressing enter for example, but dreadfully failed. I couldn't find a wait to intercept the execution of a task and pass data or select an item from a menu.
Any help on setting up a single hotKey which then triggers two or more commands?
Please note that I need to commands/tasks in the editor, not in terminal or shell. All the solutions I came across are for shell. Also inputs or text work in shell or in the editor, but not in the dropdown as in the following images, which are triggered by tasks.
Thanks.
Edit, what worked in the end. Thanks a lot #Mark
{
"version": "2.0.0",
"tasks": [
{
"label": "insertTryCatchSnippet",
"command": [
"workbench.action.tasks.runTask",
"${input:tryCatchInput}"
]
},
{
"label": "save",
"command": "${command:workbench.action.files.save}",
},
{
"label": "TryCatch",
"dependsOrder": "sequence",
"dependsOn": [
"insertTryCatchSnippet",
"save",
],
},
],
"inputs": [
{
"id": "tryCatchInput",
"type": "command",
"command": "editor.action.insertSnippet",
"args": {
"name": "TryCatch"
}
}
]
}
And this hotkey shortcut:
{
"key": "cmd+t",
"command": "workbench.action.tasks.runTask",
"args": "TryCatch"
},
Flawlessly without using macros or extensions. Thanks again.
You can run vscode commands, like editor.action.insertSnippet. But if they take arguments than I believe you have to use the inputs of tasks.json to supply the args. In your tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "insertTryCatchSnippet",
"command": [
"${input:tryCatchInput}"
],
}
],
"inputs": [
{
"id": "tryCatchInput",
"type": "command",
"command": "editor.action.insertSnippet",
"args": {
"name": "tryCatch"
}
}
where your snippet name is defined in some snippets file.
You can then assign this task directly to a keybinding like this (in your keybindings.json):
{
"key": "alt+w",
"command": "workbench.action.tasks.runTask",
"args": "insertTryCatchSnippet",
"when": "editorFocus"
}
If your desired command didn't need any args than you could do something like this in a task:
{
"label": "SplitTerminal",
"command": "${command:workbench.action.terminal.split}",
"type": "shell",
"problemMatcher": []
}
You can use multiple vscode commands in a task too (although some commands may need to wait for the previous command to finish and you should make 2+ tasks that then run from a master task with the dependsOrder property sequence):
{
"label": "open new terminal and then saveAll",
// "type": "shell",
"command": [
"${command:workbench.action.terminal.new}",
"${command:workbench.action.files.saveAll}"
]
}

Configuring a customized build task in vs code for c++

I had a custom build system in sublime for C++ which takes input from one file and redirects the output to another.
My sublime build system is as follows :
{
"cmd": ["g++.exe","-std=c++14", "${file}", "-o", "${file_base_name}.exe", "&&" , "${file_base_name}.exe<inputf.in>outputf.in"],
"selector":"source.cpp",
"shell":true,
"working_dir":"$file_path"
}
this helped in taking input from "inputf.in" file and print the output in "outputf.in" whenever i ran my program.
I want similar functionality in vs code but dont know how to configure build-task.
Here is a build task for a Node addon, you have to put it in .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "npx node-pre-gyp build -j max",
"problemMatcher": {
"base": "$gcc",
"fileLocation": [
"relative",
"${workspaceFolder}/build"
]
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
You can press Ctrl-Shift-P to bring the command palette and select configure build task.
The problem matcher allows VSCode to highlight the compiler errors in your editor.
The default build task is the one you launch with a hotkey.

How can I start debugging R or Python code using the same key in Visual Studio Code?

Trying to avoid the XY problem, my problem at the very high level: I work in a VS Code workspace with R and Python code files, and I often need to debug one or the other. Currently I have different debug launch configurations saved, and I need to switch between them manually - that is a pain. I would like to use F5 to
launch the Python debugger when the editor is active in a .py file
launch the R debugger when the editor is active in a .R file
I see many technical ways of doing that, but all have their roadblocks (some of which may just poor documentation):
Create my own extension with a dynamic debug configuration that determines the type of the active editor and starts the correct debug configuration. (A lot of effort required.)
Use a "compound" launch configuration, starting both R and Python launch configurations, and stopping all but one. This can be done using a "prelaunchTask" for each, but non-zero return codes create error message that I don't like.
Use editor-dependent key mappings ("when": "editorLangId == 'python'"), but which command for debugging to start and how to pass the launch configuration? There is vscode.startDebug which takes arguments (https://github.com/microsoft/vscode/issues/4615), but I cannot keybind to that. And then there is workbench.action.debug.start which seems to ignore arguments. And then there is vscode.commands.executeCommand to which I cannot keybind, either.
Use a multi-command extension to bind a key to something like "set debug configuration, then press F5". But how to do that?
Etc. etc.
After much fiddling, here is one solution following idea 2:
settings.json (launch configs could be put into launch.json):
{
"debug.onTaskErrors": "abort",
"launch": {
"compounds": [
{
"name": "Python/R: Current File",
"configurations": [
"Python: Current File",
"R: Current File",
],
},
],
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"preLaunchTask": "check_ext py",
"request": "launch",
// ...
},
{
"name": "R: Current File",
"type": "R-Debugger",
"preLaunchTask": "check_ext R",
"request": "launch",
// ...
}
],
},
}
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "check_ext py",
"type": "shell",
"command": "echo ${fileExtname} | grep -i ^.py$",
},
{
"label": "check_ext R",
"type": "shell",
"command": "echo ${fileExtname} | grep -i '^.R$'",
},
],
}

RUST cargo run task with arguments in vscode

Is there a way to specify arguments to a RUST cargo command running as VS CODE task?
Or should I be trying this as an NPM script? (of course, this is RUST, so I am using CARGO and npm, creating a package.json would be odd).
The Build task works fine:
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"subcommand": "build",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
},
But I have no idea where to put the arguments since I want it to be
$cargo run [filename]
{
"type": "cargo",
"subcommand": "run",
"problemMatcher": [
"$rustc"
]
}
There absolutely is, the args option allows you to pass additional arguments to your tasks and you can use various ${template} parameters to pass things like the currently opened file.
It's also worth calling out that the type of the command should probably be shell, with cargo being specified as the command itself.
For your use case, you may consider using the following (to execute cargo run $currentFile).
{
"version": "2.0.0",
"tasks": [
{
"label": "run",
"type": "shell",
"problemMatcher": [
"$rustc"
],
"command": "cargo",
"args": [
"run",
"${file}"
]
}
]
}

Is there a way to run a command with VS Code tasks?

In VS Code, I have an extension whose commands I can run by pressing F1 and searching by name. However I would like to automatically run it from a task (tasks.json). I know its full name from keyboard shortcuts.
You can run a valid command in tasks.json with the ${command:} syntax:
{
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"command": "${command:editor.action.addCommentLine}",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
The above example comments out the current line
Compound Commands
If you would like to run commands sequentially/parallel, you can use the dependsOn property to run multiple commands:
Either a string representing another task or an array of other tasks that this task depends on.
For example, let's say there's a scenario where you want to duplicate the current line you are on down, comment it out above, and arbitrarily, for demonstration purposes, focus the terminal immediately:
{
"version": "2.0.0",
"tasks": [
{
"label": "create temporary duplicate line",
"command": "${command:workbench.action.terminal.focus}",
"dependsOn": [
"duplicate line up",
"comment line out"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "comment line out",
"command": "${command:editor.action.addCommentLine}"
},
{
"label": "duplicate line up",
"command": "${command:editor.action.copyLinesUpAction}"
}
]
}
Let's say the line you duplicated was:
<div></div>
The task would run and make this:
<!-- <div></div> -->
<div></div>
And then focus on the integrated terminal
You can review their documentation on command variables and other placeholder syntax, like taking in user input for creating dynamic tasks, or using the runOn property to automatically run a task on folder startup