How to run several tasks in VSCode - visual-studio-code

I am trying to migrate to VSCode and having a problem with setting-up tasks. It is easy to define tasks in tasks.json but I would like to run several tasks simultaneously (which I can't).
Here is my use-case: I have two watchers in my project (one for gulp and another one for webpack). Plus I want to be able to run webpack task separately. When I run one of the watchers I cannot run anything else - VSCode requires me to terminate the running task at first.
In Visual Studio I used Task Runner where several tasks were running simultaneously. Is it possible to achieve the same in VSCode?

Using compound tasks, you can specify dependsOn and dependsOrder on a separate task, and run them in parallel like this:
{
"label": "start-tasks",
"dependsOrder": "parallel",
"dependsOn": [
"taskOne",
"taskTwo"
]
}

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

Related

VS Code task to toggle the status bar on debug execution

I prefer to hide the status bar in VS code but one nice feature is that it changes colour when your program is ready to debug. This is good when there is a lengthy build step as part of the preLaunchTask. I would like to unhide and hide the taskbar using tasks.json. The internal command is
workbench.statusBar.visible true
But I am not sure how I can execute this in a task by vscode
{
"label": "debug with statusbar",
"type": "process", // ?
"group": "build",
"args": [ true ],
"command": "workbench.statusBar.visible",
"dependsOn":["npm: build"]
},
{
...
It appears a custom task can either execute via shell or as a process. Is there a way to call vscode via one of these methods and execute the internal command? Or is there another way to achieve what I would like?
Editing the settings file seems to do the trick since VS Code watches it in real time.
{
"label": "debug with statusbar",
"type": "shell",
"group": "build",
"args": [
"-i",
"'/\"workbench.statusBar.visible\": false/s/.*/ \"workbench.statusBar.visible\": true/'",
"/home/myuser/.config/Code/User/settings.json"
],
"command": "sed",
"dependsOn":["npm: build"]
},
Then an equivalent task can be used for postDebugTask

Configuring multiple commands to run in parallel in VS Code tasks (to compile and autoprefix Sass)

I had previously been using Koala to compile my Sass with autoprefixing and minifying (on Windows), but have come to find that Koala is no longer maintained. I'm therefore trying to figure out how people usually compile Sass, autoprefix it, and minify it automatically on save.
I'm not super experienced with command line tools like Gulp but have used NPM enough to get to the point of being able to install Dart Sass, PostCSS, etc., and since I use VS Code, have decided that its internal Tasks feature seems like the easiest way to go.
Currently if I do this in the VS Code terminal:
sass --watch sass:. --style compressed
It works, i.e., it successfully watches for changes in the sass directory and outputs a minified .css file in the parent directory.
If I stop that and do this instead:
postcss style-raw.css --output style.css --use autoprefixer --watch
It also works. I had to rename the original .scss file because apparently postcss doesn't allow --replace and --watch at the same time.
So right now, I have style-raw.scss which compiles to style-raw.css when I run the sass command, and style-raw.css gets autoprefixed and output to style.css when I run the postcss command.
Where I'm stuck is getting both commands to run at the same time via a Task. In my tasks.json file I have:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Sass Compile",
"type": "shell",
"command": "sass --watch sass:. --style compressed | postcss style-raw.css --output style.css --use autoprefixer --watch",
"problemMatcher": [
"$node-sass"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
This is connected to the Build task, which has a keyboard shortcut of ctrl+shift+B, so my ultimate goal thus far has been to be able to just hit ctrl+shift+B to start everything up getting watched and compiled and autoprefixed, etc.
Currently though, only the Sass command runs when I use the keyboard shortcut. I found another post somewhere that said the pipe should work for multiple commands, but it doesn't seem to, or perhaps you can't --watch two things at the same time, I have no idea. I tried an array for command: but that either doesn't work or I didn't have the right format.
Or perhaps there's an entirely different and better way to go about all this, but if anyone can help with using these two commands together, that'd be much appreciated.
UPDATE: SOLUTION --------------------------------------------------------
With the kind help of #soulshined below, I got the multiple commands working (the dependsOn option was the trick), but evidently it won't run two commands with the --watch parameter in the same terminal. For my use case this wouldn't work and I eventually found this extremely helpful article that explains how to run multiple tasks in a split terminal by grouping them.
If anyone else runs across this with the same use case, here is the working tasks.json file:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Compile CSS",
"dependsOn": [
"Sass Compile",
"Prefix Output",
],
"group": {
"kind": "build",
"isDefault": true
},
},
{
"label": "Prefix Output",
"type": "shell",
"command": "postcss style-raw.css --output style.css --use autoprefixer --watch",
"presentation": {
"group": "cssCompile"
}
},
{
"label": "Sass Compile",
"type": "shell",
"command": "sass --watch sass:. --style compressed",
"problemMatcher": [
"$node-sass"
],
"presentation": {
"group": "cssCompile"
}
}
]
}
UPDATE 2: GULP --------------------------------------------------------
Randomly ran across my own post and thought I would add that I now use Gulp. I don't remember why but the VS Code tasks turned into a hassle later on, and Gulp turned out to be not that hard to learn.
Where I'm stuck is getting both commands to run at the same time via a Task
Running concurrently can be tricky to accomplish; consider taking advantage of the dependsOn property. Here is a brief example of running commands tasks consecutively:
"version": "2.0.0",
"tasks": [
{
"label": "Echo All",
"type": "shell",
"command": "echo Done",
"dependsOn": [
"Last"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Last",
"type": "shell",
"command": "echo 'Did it last'",
"dependsOn": "First",
},
{
"label": "First",
"type": "shell",
"command": "echo 'Doing it first'",
}
]
That's a language [shell] agnostic solution. If you would like to run multiple commands you can try adding a semi colon after each statement:
"command": "sass --watch sass:. --style compressed; postcss style-raw.css --output style.css --use autoprefixer --watch"

VScode remote development: How can I run a build task to source environment variables before running the real build task?

I want to setup VScode so I can use build tasks to build my project. The project is build using make, en I have defined a build task that runs make. However, before running make, I normally would source a script that sets my environment variables correctly. If I add a new build task with the source command, and set my main build tasks to first execute the source command, the environment variables are not propagated properly. How can I make sure the enviroment variables are kept between build tasks?
My tasks.json file:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "make",
"command": "make",
"args": [],
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "Set environment"
},
{
"label": "Set environment",
"type": "shell",
"command": "source path/to/source_me.sh",
"group": "build",
]
}
Not in this way. Sourcing a file is injecting file contents into current shell session, which ends as soon as the task ends. The make task is run in a separate shell session, so these two do not interact. You may try to do a single task that executes a single line: source path/to/source_me.sh && make.
I solved my problem like this:
"tasks": [
{
"label": "all",
"type": "shell",
**"command": "source gitenv.sh && cd ${fileDirname} && alfred all"**,
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
Where alfred is a macro for make command with extra args.
${fileDirname} returns a current directory in which you have open file.
So if you open a file and in the same directory you have Makefile you can CTRL + SHIFT + B to execute this default task.

Terminate another task from within a postDebugTask - VS Code

I have a debug launch configuration (launch.json) like below.
{
"version": "0.2.0",
"configurations": [
{
"name": "Current TS File",
"type": "node",
"request": "launch",
"preLaunchTask": "Pre Debug Task",
"postDebugTask": "Stop Watch Styles",
"args": ["${relativeFile}"],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"sourceMaps": true,
"cwd": "${workspaceRoot}",
"protocol": "inspector",
}
]
}
My tasks configuration (tasks.json) is like
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "next:copy",
"label": "Copy Files",
"problemMatcher": []
},
{
"type": "npm",
"script": "styles:tsw",
"label": "Watch Styles",
"problemMatcher": [],
},
{
"label": "Pre Debug Task",
"isBackground": true,
"dependsOn" :[
"Copy Files",
"Watch Styles"
]
},
{
"label": "Stop Watch Styles",
// No sure what should come here
}
]
}
Trying to stop watch process in postDebugTask, is there a way to Terminate Task by providing name (Watch Styles) as parameter in tasks.json. Watch styles is a continuously running process, please suggest if there is any other approach to terminate a task after debugging is complete.
This will terminate all tasks after debug stops
Or in this case, just build_runner watch...
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Flutter",
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"preLaunchTask": "flutter: build_runner watch",
"postDebugTask": "Terminate All Tasks"
}
]
}
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Terminate All Tasks",
"command": "echo ${input:terminate}",
"type": "shell",
"problemMatcher": []
}
],
"inputs": [
{
"id": "terminate",
"type": "command",
"command": "workbench.action.tasks.terminate",
"args": "terminateAll"
}
]
}
More info here: https://code.visualstudio.com/docs/editor/variables-reference#_command-variables
This works for me:
{
"label": "postdebugKill",
"type": "process",
"command":[
"${command:workbench.action.tasks.terminate}",
"${command:workbench.action.acceptSelectedQuickOpenItem}",
],
},
The first "${command:workbench.action.tasks.terminate}" will bring up a panel asking you to select which task to terminate. So if you had multiple running tasks and wanted to choose one you would use this command only.
The second "${command:workbench.action.acceptSelectedQuickOpenItem}" will terminate the selected task in that panel mentioned above. (So you will not even see the terminate panel.) If you have only one running task when you call the postdebugKill task, it will be selected automatically and thus terminated. Otherwise whichever task is listed first will be terminated. Again, if you have more than one other task running and you want to select which to terminate don't include this second command.
I don't know of any way to list, perhaps via an args option a label name for which task to terminate if running. It would be nice to have this functionality.
[postdebugKill name can be whatever you want.]
To call a postdebug task your launch.json config might look like this:
{
"type": "node",
"request": "launch",
"name": "Gulp: serve",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"args": [
"serve"
],
// "preLaunchTask": "someTask",
"postDebugTask": "postdebugKill"
},
Upon stopping that "Gulp: serve" debugging session, the task "postdebugKill" will be triggered. And so if I had used the "preLaunchTask" to start a task or had simply started a task running before launching the "Gulp: serve" debugging session - that preLaunchTask would be terminated.
The ability to run vscode commands in a task was recently added to vscode. Some minimal info here: using a command in a task doc.
[I'll add another answer because the new additional info is extensive.]
It seems there is an issue with running a preLaunchTask and then launching a debugging session. See particularly debugging does not work on first try. It appears to be fixed though in an insiders edition and may be released in early February 2019. terminal not sending onLineData.
In the meantime there is a suggested fix within one of the issues that I have lost the link to and that is a problemMatcher which will signal to the debugger that the dependent tasks have completed.
In my watching task I used this:
"problemMatcher": [
{
"base": "$tsc-watch",
"background": {
"activeOnStart": true,
"beginsPattern": "Using gulpfile ~\\OneDrive\\experimental\\gulpfile.js",
"endsPattern": "Starting 'watch'..."
}
}
],
I chose that because when I manually start the gulp:watch task I get this in the terminal:
[22:27:48] Using gulpfile ~\OneDrive\experimental\gulpfile.js
[22:27:48] Starting 'watch'...
[22:27:48] Starting 'watch'...
So you see the start and end pattern there that I copied (with extra escaping).
I suggest that you separately run your "Pre Debug Task" and copy the start and ending output into your "Pre Debug Task" problemMatcher and see if it now works.
My code in the first answer I believe is correct, I just wasn't using "isBackground" and "dependsOn" as you are. But I have added "isBackground" to mine and the problemMatcher option and it works flawlessly now.
Hopefully, this will be fixed in the next February 2019 release and there will be no need for this workaround.
If on Linux or macOS, a less hacky solution that just works is using pkill. If on Windows, see below.
First run the task and find the full command vscode runs for that task, with $ ps -af
Then use pkill + the full command in a postDebugTask.
I have an entry in tasks.json like this:
{
"label": "stop npm:watch",
"type": "shell",
"command": "pkill -f 'sh -c node ./scripts/watch.js'",
"presentation": {
"reveal": "silent",
"panel": "dedicated",
"close": true,
}
}
'sh -c node ./scripts/watch.js' is how vscode runs my npm:watch task.
The presentation properties prevent this task from taking focus or taking up terminal space after it finishes successfully.
Then you reference that task in a launch.json configuration:
{
...
"preLaunchTask": "npm:watch",
"postDebugTask": "stop npm:watch",
...
}
If the full command contains changing parameters (paths, port numbers, etc.), you can use a part of the command or regex.
e.g.: I could have probably matched with './scripts/watch.js' or 'node.*watch'.
For Windows: you can make this work by substituting pkill for taskkill.
If you want to support both Unix and Windows, you can make a script that does one or the other depending on the underlying OS.

How to run several tasks as a group?

I created two tasks to assist me in the development of a web site:
{
"version": "2.0.0",
"tasks": [
{
"taskName": "build site",
"command": "jekyll b --watch --incremental",
"type": "shell",
"group": "build"
},
{
"taskName": "serve site",
"command": "./_devd -ol _site",
"type": "shell",
"group": "build"
}
]
}
I can start them one by one with F1 → Run Task (so I need to issue the sequence twice, once for each task) and I end up with two tasks running at the same time.
Is it possible to automate this and run a group of tasks at the same time? I thought that the group entry would, well, group them together but it is not the case (they are just recognized as belonging to the build or test group - and I did not find a way to start the whole group at once).
You can use the "dependsOn" attribute. If you want to run the "build site" task first, add it as the "dependsOn" of the "serve site" task. If you want both to run together, make another task that depends on both the "build site" and "serve site" tasks.
Here is an example of building the site before serving it:
{
"taskName": "build site",
"command": "jekyll b --watch --incremental",
"type": "shell",
"group": "build"
},
{
"taskName": "serve site",
"command": "./_devd -ol _site",
"type": "shell",
"group": "build",
"dependsOn": "build site" // <--- Added this
},
Not aware of a cleaner way to do this with long running tasks but...
Here is an example of running both tasks at the same time:
{
"taskName": "Run Everything", // <-- Bind this task to a key
"dependsOn": [ "build site", "serve site" ]
},
{
"taskName": "build site",
"command": "jekyll b --watch --incremental",
"type": "shell"
},
{
"taskName": "serve site",
"command": "./_devd -ol _site",
"type": "shell"
}
Update: Here's a link to the documentation for the new tasks.json template (v2.0.0). The portion relevant to this question is that taskName has been renamed to label, but dependsOn's value remains the same.