VSCode: Open new terminal as part of task? - visual-studio-code

Visual Studio Code was just updated to allow running a task and having them open in a split terminal. This is great, however I'm looking for one more thing to make this perfect.
I would like to be able to open a total of 3 terminals via a task. One for my NPM build, one for my backend MAVEN build, and a third that is just a blank new terminal I can use for git commands when needed.
I can't seem to find a way to tell VSC to run a task that just opens a new terminal ready to use without providing it a command. I would even settle with giving it a simple command like "node -v" just to start it out, as long as that panel is still usable after. Right now it wants to close it after it has ran.
Here is my task setup: I have one task setup as the build task that depends on two others. I envision adding a third one to that which would just open the new terminal:
{
"version": "2.0.0",
"tasks": [
{
"label": "Run Maven and NPM",
"dependsOn": [ "maven", "npm" ],
"group": {
"kind": "build",
"isDefault": true,
},
},
{
"label": "maven",
"command": "...",
"type": "shell",
"presentation": {
"reveal": "always",
"group": "build"
},
"options": {
"cwd": "${workspaceRoot}/server"
}
},
{
"label": "npm",
"type": "shell",
"command": "ng serve --port 4203 --proxy-config proxy.conf.json",
"presentation": {
"reveal": "always",
"group": "build"
},
"options": {
"cwd": "${workspaceRoot}/client-APS"
}
}
]
}

The following should work:
{
"type": "process",
"label": "terminal",
"command": "/bin/bash", // <-- your shell here
"args": [
"-l" // login shell for bash
],
"problemMatcher": [],
"presentation": {
"echo": false, // silence "Executing task ..."
"focus": true,
"group": "build", // some arbitrary name for the group
"panel": "dedicated"
},
"runOptions": {
"runOn": "folderOpen"
}
}
I was trying to achieve something very similar when I stumbled my way into this solution: Here, I'm auto-launching (and setting the focus on) the terminal when the folder is opened in vscode -- and further tasks that share the same presentation.group gets placed in split terminals when they're run (with new vs. reused splits depending on their presentation.panel)
(The runOptions bit is superfluous for your case, but I'm keeping it in case it is helpful for someone)
Note: For this example, you may or may not need the -l option depending on your settings for terminal.integrated.shell*, terminal.integrated.automationShell* and terminal.integrated.inheritEnv -- this issue has some discussion on what is involved in setting up the shell environment.

Related

Open Integrated WSL terminal at specific directory with VSCode Task

I'm working with VSCode Tasks and my goal is to simply open a set of integrated WSL terminals and navigate each to a specified directory when the workspace launches.
I'm using the workspace's tasks object and currently can launch WSL terminals, but can't seem to specify the directory.
Below is my current configuration. It launches my wsl terminals no problem, but with cwd does not correctly map. When using cmd.exe instead of wsl, it works fine.
"tasks": {
"version": "2.0.0",
"tasks": [
//Worker Task to Open Each Terminal.
{
"label": "Create terminals",
"dependsOn": [
"WSL_Terminal_1",
"WSL_Terminal_2",...
],
"group": {
"kind": "build",
"isDefault": true
},
//Run When Workspace Opens.
"runOptions": {
"runOn": "folderOpen"
}
},
//Single Terminal Task.
{
"label": "WSL_Terminal_1",
"type": "shell",
"command": "",
"options": {
"cwd":"/mnt/c/my/working/dir",
"shell": {
"executable": "C:\\...\\ubuntu2004.exe",
}
},
"icon": {"color": "terminal.ansiMagenta", "id": "terminal-linux" },
"isBackground": true,
"problemMatcher": [],
"presentation": {
"echo": false,
"focus": false,
"reveal": "always",
"panel": "new",
}
},
...
I've tried some combination of args with no success
//tested 1
"shell": {
"executable": "C:\\...\\ubuntu2004.exe",
"args": ["-c 'cd /mnt/c/my/working/dir'"],
}
//tested 2
"shell": {
"executable": "C:\\...\\ubuntu2004.exe",
"args": ["-c",
"cd /mnt/c/my/working/dir"
],
}
I tried several versions of cwd as well with no positive results
//Throws Error on running task
"cwd":"/mnt/c/my/working/dir"
//No error but WSL terminal still opens at /home/user
"cwd":"C:\\my\\working\\dir"
//Linux Side Paths also not working
"cwd":"/home/user/test_dir"
"cwd":"test_dir"

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 to re-use a VS Code task window, without closing it

My goal is to re-use a task window in VS Code. However, when I enter ctrl + c, the task stops, but then writes: "Terminal will be reused by tasks, press any key to close it.".
I don't want to close the window. It's frustrating because it forces me to open a new window and navigate to the correct directory.
I recorded a gif of the problem (It's the window on the right):
My task config look like this:
{
"label": "some label",
"type": "npm",
"script": "build",
"path": "some-path/",
"problemMatcher": [],
"runOptions": { "runOn": "folderOpen" },
"group": "build",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": false,
"group": "build"
}
}
I tried various combination of the presentation properties, but to no help.
Related feature request on VS code is here.
I don't think this is possible and it may be by design.
If you look at the schema of tasks.json, you see:
/**
* The description of a task.
*/
interface TaskDescription {
/**
* The task's name
*/
label: string;
/**
* The type of a custom task. Tasks of type "shell" are executed
* inside a shell (e.g. bash, cmd, powershell, ...)
*/
type: 'shell' | 'process';
//...
}
The type of a custom task. Tasks of type "shell" are executed inside a shell
So to me this implies that if you have a countdown task of type "shell" running this command seq 10 1, behind the scene it would do:
devbox:~ dev$ bash -c "seq 10 1"
10
9
8
7
6
5
4
3
2
1
devbox:~ dev$
As you can see it immediately exits and I'm not sure you can do anything about it. (I may be wrong though)
Even if you set a task of type "process" (command being the path to an executable), it doesn't allow you to reuse the terminal.
Having said that you can force it but VS Code wouldn't be too happy about it: (notice the && sh at the end of the command)
{
"version": "2.0.0",
"tasks": [
{
"label": "10 9 8 ...",
"type": "shell",
"command": "seq 10 1 && sh",
"presentation": {
"echo": true,
"focus": true,
"reveal": "always",
"panel": "shared",
},
"problemMatcher": [],
}
]
}
When you run the task, you do get another shell immediately:
However if you re-run the same task, then VS Code gets grumpy:
The fact that I couldn't see an option in .vscode/settings.json to support your use case makes me think that it really is a by design choice:
I found yet another solution for this that works great for me:
using bash:
"tasks": [
{
"label": "start server",
"type": "shell",
"command": "bash -c 'cd backend && npm run dev; exec bash'",
"isBackground": false,
"presentation": {
"panel": "new",
"close": true
},
"runOptions": {
"runOn": "folderOpen"
}
}
]
or if you use fish (like me):
"tasks": [
{
"label": "start server",
"type": "shell",
"command": "fish -C 'cd backend && npm run dev'",
"isBackground": false,
"presentation": {
"panel": "new",
"close": true
},
"runOptions": {
"runOn": "folderOpen"
}
}
]
It sounds like you want to launch a shell in the right folder after the task is complete. I'm not sure if this is the best way to do it, but I do something similar with compound tasks.
{
"label": "some label",
"type": "npm",
"script": "build",
"path": "some-path/",
"problemMatcher": [],
"runOptions": { "runOn": "folderOpen" },
"group": "build",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": false,
"group": "build"
}
},
{
"label": "shell",
"type": "shell",
"command": "cd app; bash",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Task and Shell",
"group": "build",
"dependsOn": ["some label", "shell"],
"dependsOrder": "sequence",
}
This configuration runs bash in the right folder after the task (in the same window). Replace bash with whatever shell you use if necessary.
I found a solution for this, my task looks something like this
"tasks": [
{
"label": "start server",
"type": "shell",
"command": "RUN='cd backend && npm run dev' bash",
"problemMatcher": [],
},
]
and at the end of my .bashrc I have eval "$RUN"

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.

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.