VS CODE SaveAll from Task - visual-studio-code

I want to execute SaveAll from a task such as evoking workbench.action.files.saveAll from within Task.
The objective is to make sure all files are saved before triggering series of other Tasks.
Task #1: SaveAll (workbench.action.files.saveAll)
Task #2: Run Grunt that dependsOn Task#1
The tasks.json looks something like this
{
"version": "2.0.0",
"tasks": [
{
"command": "workbench.action.files.saveAll",
"label": "SaveAllFiles",
},
{
"type": "grunt",
"task": "default",
"label": "Execute Grunt",
"dependsOn": [
"SaveAllFiles"
],
"problemMatcher": []
}
]
}
In theory, all I should have to do is execute the task labeled Execute Grunt, and it will call the SaveAllFiles task. To be precise, I don't want to trigger tasks based on Save or SaveAll events; there are times when I want to save files, but not trigger other tasks.

{
"label": "SaveAllFiles",
"command": "${command:workbench.action.files.saveAll}",
"type": "shell",
"problemMatcher": []
},
{
"type": "grunt",
"task": "default",
"label": "Execute Grunt",
"dependsOn": [
"SaveAllFiles"
],
"dependsOrder": "sequence", // need this, "parallel" is the default otherwise
"problemMatcher": []
}
${command:workbench.action.files.saveAll} is the general form for calling a vscode command, you can also call extension or macro commands this way.
The info on this is in https://code.visualstudio.com/docs/editor/variables-reference#_command-variables which makes it a little tricky to find as it isn't in the Tasks documentation.

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}"
]
}

How to run tasks in sequence?

I would like to configure one task labeled "Build and then Run" that would execute a specific build task and then run the executable. I thought that the dependsOn property was what I was looking for but as it turns out it runs the tasks in parallel instead.
Here is an example of tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "g++ -g ${workspaceFolder}/main.cpp -o ${workspaceFolder}/main.exe",
"problemMatcher": "$gcc"
},
{
"label": "Run",
"type": "shell",
"command": "${workspaceFolder}/main.exe"
},
{
"label": "Build and then Run",
"type": "shell",
"dependsOn": [ // <------ important
"Run",
"Build"
]
}
]
}
It doesn't matter in what order I put the tasks into the dependsOn array. The "Run" task executes with error because the "Build" task creates the executable too late.
Is there some property or trick that allows two tasks to run in sequence?
{
"label": "Build and then Run",
"type": "shell",
"dependsOrder": "sequence", <= `parallel must be the default
"dependsOn": [
"Run",
"Build"
]
}
If you specify "dependsOrder": "sequence" then your task dependencies
are executed in the order they are listed in dependsOn. Any
background/watch tasks used in dependsOn with "dependsOrder":
"sequence" must have a problem matcher that tracks when they are
"done".
from https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks
That implies to me, plus your experience, that omittiing the option dependsOn means by default the tasks will run in parallel, not in sequence.

Using a shell command as VSCode task variable value

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.

How to run multiple tasks in VS Code on build?

Using tasks.json version 2.0.0, I have not been able to make it so that, when I build my application, multiple tasks are run at the same time. I'm using gulp for my SCSS compilation, and running my Compile/minify cms.scss task on its own works fine, so it's not a problem with the task itself, just VS Code's task runner. When I Run Build Task in VS Code, my gulp task is not being run, even though it has "group": "build" — only the dotnet one is.
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/HpsCoreWeb.csproj"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Compile/minify cms.scss",
"type": "gulp",
"task": "cms.scss:cms.min.css",
"problemMatcher": "$node-sass",
"group": "build"
}
]
}
According to the VS Code Tasks documentation:
group: Defines to which group the task belongs. In the example, it belongs to the test group. Tasks that belong to the test group can be executed by running Run Test Task from the Command Palette.
The dotnet build task is succeeding, so shouldn't the other task, which is also part of the build group, be run as well? What am I doing wrong?
The problem is that "Run Test Task" and "Run Build Task" do not execute all tasks in that specific group. Usually you get a drop down selection so you can choose which task to execute. Since you have specified one of the tasks as default, the selection will be skipped and instead the default task is executed.
You can work around that by adding dependencies. Take the following example:
{
"version": "2.0.0",
"tasks": [
{
"label": "Echo 1",
"command": "echo",
"type": "shell",
"args": [ "echo1" ],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn":["Echo 2"]
},
{
"label": "Echo 2",
"type": "shell",
"command": "echo",
"args": [ "echo2" ],
"group": "build"
}
]
}
As Echo 1 depends on Echo 2, Echo 2 will be executed prior to executing Echo 1. Note that the definition is a list, so more than one task can be specified. In that case the tasks are executed in parallel.
In your case adding "dependsOn":["Compile/minify cms.scss"] to your main build task should execute both tasks.
You can use Compound Tasks.
The example below executes "Client Build" and "Server Build" tasks when "Build" task is called.
{
"version": "2.0.0",
"tasks": [
{
"label": "Client Build",
"command": "gulp",
"args": ["build"],
"options": {
"cwd": "${workspaceFolder}/client"
}
},
{
"label": "Server Build",
"command": "gulp",
"args": ["build"],
"options": {
"cwd": "${workspaceFolder}/server"
}
},
{
"label": "Build",
"dependsOn": ["Client Build", "Server Build"]
}
]
}
Add 'gulp-load-plugins' plugin in package.json
var gulpLoadPlugins = require('gulp-load-plugins'),
plugins = gulpLoadPlugins();
To read more about that plugin, see How To Build And Develop Websites With Gulp
Double check your settings are enabled for Gulp auto-detection:
"gulp.autoDetect": "on"

Any source or idea, how to do delayed compound in VSCode?

I have a build task that takes at least 2 seconds to finish in tasks.json.
I also have different very quick task for cleaning some files in tasks.json.
I have 3 configurations in launch.json: server, server_running_on_top_of_server and client. All of them can be running separately, so all of them should have the build as a preLaunchTask.
So if I run those 3 configurations separately with build as preLaunchTask and cleaning specified in dependsOn of build, it's quite fine.
But when I want to run those 3 configurations together as a compound, it's not very intuitive. I would like to first run build task and then server and after the server is up, then server_running_on_top_of_server and client. The cleaning configuration should be run only for the client, but can be run everytime the build task is run.
"compounds": [
{
"name": "server, server_running_on_top_of_server and client",
"configurations": ["server", "server_running_on_top_of_server", "client"]
}
and
"tasks": [
{
"label": "build",
"type": "shell",
"command": "make",
"args": [
"-j4",
"debug"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "delete something",
"presentation": {
"panel": "shared"
}
},
{
"label": "delete something",
"type": "shell",
"command": "rm",
"args": [
"-f", "something"
],
"presentation": {
"panel": "shared"
}
},
{
"label": "wait 5 seconds",
"type": "shell",
"command": "sleep",
"args": [
"5"
]
}
]
But the build task is run 3 times this way and also separately in 3 terminals even with presentation.panel: "shared" so it uses 12 cores instead of 4 so it totally lags my PC. How to fix that?
And how to run the remaining 2 configurations after the server is up? Is there a better approach than to create another task that just waits some time?
Is there a possibility to specify more than 1 task in preLaunchTask? So I can assign build and cleaning task only for client.