Is it possible to specify user specific pre commands in VS Code? - visual-studio-code

We have a slew of folks doing development through the same GitLab repo. We are using VS Code tasks to execute internal commands. The main command is the same for everyone: internal_command on Windows and internalCommand on Linux.
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label" : "do it",
"type" : "shell",
"windows": {
"command": "internal_command"
},
"linux": {
"command": "internalCommand"
}
}
]
}
This works as expected.
Some users need/want to run a specific command before the main command. For example, one use wants to rename a file, another user wants to change an environment variable, etc...
We don't want to have multiple versions of .vscode/tasks.json cause that is a mess when pushing things to GitLab.
So I am wondering if there is a way to specify user specific tasks in the project's .vscode/tasks.json file?

You can with the help of the extension Command Variable it allows you to use the content of a file as a command in the terminal. The file can also contain Key-Value pairs or be a JSON file.
Say you store this userTask.txt or userTask.json file in the .vscode folder and add the file to the .gitignore file.
With the current version of the extension the file userTask.txt has to exist, I will add an option to supply alternative text in case the file does not exist. You can fill the file with a dummy command like echo No User Task
Set up your task.json like
{
"version": "2.0.0",
"tasks": [
{
"label" : "do it",
"type" : "shell",
"windows": {
"command": "internal_command"
},
"linux": {
"command": "internalCommand"
},
"dependsOrder": "sequence",
"dependsOn": ["userTask"]
},
{
"label" : "userTask",
"type" : "shell",
"command": "${input:getUserTask}"
}
],
"inputs": [
{
"id": "getUserTask",
"type": "command",
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/.vscode/userTask.txt"
}
}
]
}

Related

Visual Studio Code User Individual Configuration for Project

I have a project created with defined tasks, for other users to use in my institution.
But now one of my tasks needs a parameter that should be a user defined directory.
How can each user have a configuration file in their project that my tasks can read and get the directory they want the out put to go?
This is a example of my task :
{
"label": "Generate File",
"type": "shell",
"command": "cscript.exe",
"args": [
"//NoLogo",
"${workspaceFolder}/scripts/build.vbs",
"0",
"${output}",
],
"options": {
"cwd": "${workspaceFolder}"
},
The output should be a folder define by each of the users in a configuration or setting file they can put in their project.
Edit :
As Requested i tried to do this
inside my .vscode folder i created a file named settings.json
with this as content
{
"env": {
"dirLoc": "C:\\output\\"
}
}
and tried to use this variable in my tasks.json file
{
"label": "Generate File",
"type": "shell",
"command": "cscript.exe",
"args": [
"//NoLogo",
"${workspaceFolder}/scripts/build.vbs",
"0",
"${env:dirLoc}",
],
"options": {
"cwd": "${workspaceFolder}"
},
but still i did not get anything in the value, it came blank
You can use the extension Command Variable.
It has the command extension.commandvariable.file.content where you can read file content and use it in a variable in the task or launch.
The file can be plain text, key-value, json and yaml.

Is it possible to use input variables in keybindings in VS Codium?

In Visual Studio Codium I want to define a command that has a variable parameter.
I want the IDE to open specific file, which name is written in another file. Assume I have the following project structure:
/home/user/myproject/
/home/user/myproject/dir1/
/home/user/myproject/dir1/problem1.py
/home/user/myproject/dir1/problem2.py
/home/user/myproject/dir2/problem1.py
...
/home/user/myproject/pointer.txt
The pointer.txt contains path to the file I want to work on. For example, it contains:
dir1/problem1.
I have read the documentation here. Now I created the following construction:
keybindings.json:
{
"key": "numpad3",
"command": "htmlRelatedLinks.openFile",
"args": {
"file": "${workspaceFolder}/${input:mycatinput}.py",
"method": "vscode.open",
"viewColumn": 2,
}
},
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "mycat",
"type": "shell",
"command": "cat /home/user/myproject/pointer.txt"
},
],
"inputs": [
{
"id": "mycatinput",
"type": "command",
"command": "workbench.action.tasks.runTask",
"args": "mycat"
}
]
}
But when I press numpad3, I get an error notification with text: Unable to open '${input:mycatinput}.py': File not found.
Am I missing something? How do I specify a variable in keybindings.json command, which itself is a result of another command (a shell command, not a vscode command).
In HTML Related Links v0.17.0 is it possible to use a ${command} variable.
Together with the extension Command Variable you can read the file content and use it.
{
"key": "numpad3",
"command": "htmlRelatedLinks.openFile",
"args": {
"file": "${workspaceFolder}/${command:mypointer}.py",
"method": "vscode.open",
"viewColumn": "2",
"command": {
"mypointer": {
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/pointer.txt"
}
}
}
}
}
Command Variable can also read Key-Value files, JSON files, and you can construct a pick list or prompt string, and you can transform the content if needed.

How to simultaneously create a new folder and multiple files in VSCode?

I discovered recently in Visual Studio Code that I can create a new folder and a new file simultaneously by using the following patten: Test/Test.jsx
eg.
1: Right click and select 'New File'.
2: Enter desired folder and file name.
3: The result from step 1 & 2.
Anyone know if it's possible to create a folder with multiple files using a similar pattern? This is what I'd like to be able to do.
I don't think you can do it the way you showed, but it is pretty easy to do it with a task. In your tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "new react folder and files",
"command": "mkdir ${input:dirName} && touch '${input:dirName}/${input:dirName}.component.jsx' '${input:dirName}/${input:dirName}.styles.jsx'",
"type": "shell",
"problemMatcher": [],
"presentation": {
"echo": false,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
}
],
// ........................................................................................
"inputs": [
{
"type": "promptString",
"id": "dirName",
"description": "Complete my folder name",
"default": "jsx folder to create"
}
]
}
And some keybinding to trigger the task (in your keybindings.json):
[
{
"key": "alt+j",
"command": "workbench.action.tasks.runTask",
"args": "new react folder and files",
}
]
This will prompt for the directory name and then create the folder and two files within it.
[I used bash commands mkdir and touch to create the folder and files, if you are using a shell without those commands swap out the ones you have.]

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.

Is there a VS Code shortcut for creating a new file from selected or clipboard code?

I work with large html files that I would like to fragment into separate files. The process of doing this is quite tedious as it requires copying the code, creating a new file, pasting it in the new file, and then selecting a folder and a new name to save it under.
Is there a built-in shortcut, macro or extension for VS Code for making this easier?
Just a note for others that since this is an html file, the new refactor Move to a new file is not available. It does what you want and will work in many other languages, but not html. You can access it by selecting the text to move and in the context menu choose Refactor.. - it may even add import statements to the old file if supported.
Here is a macro which does what you want. I am using the macro extension multi-command but there are others.
In settings.json:
"multiCommand.commands": [
{
"command": "multiCommand.newFileWithContent",
"sequence": [
// choose which one you want
"editor.action.clipboardCutAction",
// "editor.action.clipboardCopyAction",
"workbench.action.files.newUntitledFile",
"editor.action.clipboardPasteAction",
// prompt for save immediately?
"workbench.action.files.saveAs",
]
},
Then trigger it either through the command palette (search for "multi") or with a keybinding (keybindings.json):
{
"key": "strl+alt+b", // your keybinding choice
"command": "extension.multiCommand.execute",
"args": { "command": "multiCommand.newFileWithContent" }
},
I don't know how to automate the "selecting a folder and a new name to save it under" part of your question. I think you are still going to have to do that manually, but there is some handy "intellisense" for that in the "saveAs" dialog.
Update in 2020
After I came up with this answer, see in vscode how can I quickly generate a new file with datetime in the name?
I thought there might be a better way to handle creating the file with a task and prompting for a folder and filename in one go. You lose the saveAs intellisense on your folder structure, but it is a pretty good technique to know in any case. And a macro isn't needed. In a bash shell:
{
"version": "2.0.0",
"tasks": [
{
"label": "newFile",
// assuming your folder name isn't static
"command": "echo '${selectedText}' > ${input:folderName}/${input:fileName}.html",
"type": "shell",
"problemMatcher": [],
"presentation": { // terminal handling which you may not care about and could delete
"echo": false,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"promptOnClose": false
}
],
"inputs": [
{
"type": "promptString",
"id": "folderName",
"description": "Complete my folder name.",
"default": "folder"
},
{
"type": "promptString",
"id": "fileName",
"description": "Complete my file name.",
"default": "new file name"
}
]
}
Some keybinding to run that task (or just run it from the command palette Run Task command):
{
"key": "alt+r", // whatever you choose
"command": "workbench.action.tasks.runTask",
"args": "newFile"
},
That's it, select your task, and run the task Alt+R.