Prevent asynchronous order of command sequence execution in VS Codium - visual-studio-code

How can I control the execution order of multiCommand extension? It behaves like it executes them in parallel, while I want them to be executed one after another.
I have a project with the following structure:
/home/user/myproject/dir1/problem1.py
/home/user/myproject/dir1/problem1.txt
/home/user/myproject/dir1/problem2.py
/home/user/myproject/dir1/problem2.txt
...
/home/user/myproject/pointer.txt
The pointer.txt contains the text: dir1/problem2.
I want to press a shortcut, and do a sequence of actions:
Create next problem files pair
Modify a pointer.txt to point to new files
Open them in the editor
I setuped the following things.
In settings.json I defined the command sequence named "openPointedProblemLayout" (for being able to easily reuse it):
"multiCommand.commands": [
{
"command": "multiCommand.openPointedProblemLayout",
"sequence": [
{ "command": "htmlRelatedLinks.openFile",
"args": {
"file": "${command:mypointer}.py",
"method": "vscode.open",
"viewColumn": 1,
"command": {
"mypointer": {
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/pointer.txt"
}
}
}
}
},
{ "command": "htmlRelatedLinks.openFile",
"args": {
"file": "${command:mypointer}.txt",
"method": "vscode.open",
"viewColumn": 2,
"command": {
"mypointer": {
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/pointer.txt"
}
}
}
}
},
]
},
]
In tasks.json I created a shell command definition, that creates a new .py and .txt pair and also changes the pointer:
{
"version": "2.0.0",
"tasks": [
{
"label": "create_new_problem_files_pair",
"type": "shell",
"command": "python /home/user/scripts/create_new_problem_files_pair.py \"${file}\""
},
],
}
In keybindings.json I defined shortcut numpad2 that executes both actions (creates files and opens them) and a numpad5 (just opens them):
{
"key": "numpad2",
"command": "extension.multiCommand.execute",
"args": {
"sequence": [
{
"command": "workbench.action.tasks.runTask",
"args": "create_new_problem_files_pair"
},
{
"command": "multiCommand.openPointedProblemLayout"
},
]
}
},
{
"key": "numpad5",
"command": "extension.multiCommand.execute",
"args": { "command": "multiCommand.openPointedProblemLayout" },
},
Now, when I press numpad2, the two new files are created:
/home/user/myproject/dir1/problem3.py
/home/user/myproject/dir1/problem3.txt
And then two files are opened in layout (means the command actually runs), but wrong files. They are problem2.py and problem2.txt, i.e. the previous pointer is used.
I checked the content of the pointer.txt now, and it actually contains dir1/problem3. And when I press numpad5, they are opened correctly.
Why does the VS Codium uses previous content of pointer, while at the moment of command run, it should already take the new content? It looks like VS Code executes the command sequence in parallel, instead of sequence them.
Am I doing something wrong? Is that an issue with configuration or vs code itself or maybe in multiCommand extension?

I have solved the problem by avoiding usage of any extensions. A command sequence can be defined via Tasks. See https://stackoverflow.com/a/72201981/7869636
In keybindings.json I define:
{
"key": "numpad2",
"command": "workbench.action.tasks.runTask",
"args": "create_new_problem_files_pair_and_open_file_pair_in_layout"
},
And in tasks.json I defined the whole things:
{
"version": "2.0.0",
"tasks": [
{
"label": "create_new_problem_files_pair",
"type": "shell",
"command": "python /home/user/scripts/create_new_problem_files_pair.py \"${file}\""
},
{
"label": "open_file_pair_in_layout",
"dependsOrder": "sequence",
"dependsOn": [
"open_in_layout_left",
"open_in_layout_right",
],
},
{
"label": "create_new_problem_files_pair_and_open_file_pair_in_layout",
"dependsOrder": "sequence",
"dependsOn": [
"create_new_problem_files_pair",
"open_file_pair_in_layout",
],
},
{
"label": "open_in_layout_left",
"command": "${input:open_in_layout_left}",
},
{
"label": "open_in_layout_right",
"command": "${input:open_in_layout_right}",
},
],
"inputs": [
{
"id": "open_in_layout_left",
"type": "command",
"command": "htmlRelatedLinks.openFile",
"args": {
"file": "${command:mypointer}.py",
"method": "vscode.open",
"viewColumn": 1,
"command": {
"mypointer": {
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/pointer.txt"
}
}
}
}
},
{
"id": "open_in_layout_right",
"type": "command",
"command": "htmlRelatedLinks.openFile",
"args": {
"file": "${command:mypointer}.txt",
"method": "vscode.open",
"viewColumn": 2,
"command": {
"mypointer": {
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/pointer.txt"
}
}
}
}
}
]
}
This approach has a benefit that it defines these tasks in a scope of that project's workspace, and not globally in setting.json.

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

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 can I change the Predefined variables in vscode json file

for example:
when I run the tasks.json:
{
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo ${workspaceFolder}\\bulid\\${relativeFileDirname}\\${fileBasenameNoExtension}.exe"
}
],
"version": "2.0.0"
}
it print
C:\Users\***\OneDrive\***\CLion\bulid\CourseBook\0201_SqList\SqList-main.exe
because my filename was SqList-main.c.
But what I want is Sqlist.exe.
Can I do something to let it print?
C:\Users\***\OneDrive\***\CLion\bulid\CourseBook\0201_SqList\SqList.exe
I want a smart or auto method because I have many files to change.
tips: the .c file can not rename for some reason.
Using extension Command Variable v1.6.0 there is a command that can transform a number of variables.
For this case you have to modify task.json
{
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo ${workspaceFolder}\\build\\${relativeFileDirname}\\${input:noMain}.exe"
}
],
"inputs": [
{
"id": "noMain",
"type": "command",
"command": "extension.commandvariable.transform",
"args": {
"text": "${fileBasenameNoExtension}",
"find": "-main"
}
}
]
}
You can use any regular expression as find and define a replace string with capture group references ($1), and the flags to use to construct the regular expression.

How to launch specific task from input variable in VS Code?

I'm trying to create a launch configuration where an environment variable is dynamically determined by a shell script. Even though a command variable can start a task via workbench.action.tasks.runTask, it doesn't seem to be possible to specify which task to run. Input variables seem to be a little more flexible in that regard, but I can't seem to get it to work. Here is what I got:
launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": []
}
],
"inputs": [
{
"type": "command",
"id": "foo",
"command": "workbench.action.tasks.runTask",
"args": {
"args": "bar",
}
}
]
}
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "bar",
"type": "shell",
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1"
}
]
}
The issue is that the user is still queried for which task to run. I'm most insecure about the inputs.args section of the launch.json. I don't really know what the key value should be. Perhaps the implementation helps to figure this out?
This answer not really relates to make use of a vscode task, but your introducting sentence offers the motivation/what is intended to be solved.
I was faced to the same question and was wondering about vscode's input type:command. It offers a way to embed a (custom) vscode command -- which looks like a powerfull mechanism to embed a (custom) extension here. But I didn't found a builtin command that simply executes a shell script and returns it stdout. Thus an extension to capture the output of a shell command is imho required todo the trick.
E.g. https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input
provides a command shellCommand.execute doing exactly this.
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": []
}
],
"inputs": [
{
"id": "foo",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1",
"cwd": "${workspaceFolder}",
/* To prevent user from selecting output (if there is just
one line printed by command), un-comment next line */
//"useSingleResult": true
}
}
]
}
(Inspired by https://stackoverflow.com/a/58930746/1903441)
In your launch.json, try replacing
"args": {
"args": "bar",
}
with
"args": "bar"
It seems that in vscode, you cannot pass a return or even an environment variable from task.json to launch.json. But you can use a file as a intermediate.
For example, in task.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "bar",
"type": "shell",
"command": "find /dev -name 'myspecialdevice*' -maxdepth 1 > ${workspaceFolder}/.vscode/temp"
}
]
}
In launch.json you set bar as preLaunchTask, and later access the file using inputs, like this:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"env": {
"XXX": "${input:foo}"
},
"args": [],
"preLaunchTask": "bar",
}
],
"inputs": [
{
"id": "foo",
"type": "command",
"command": "extension.commandvariable.file.content",
"args": {
"fileName": "${workspaceFolder}/.vscode/temp",
}
}
]
}
To get the comment working, just install this extension: https://marketplace.visualstudio.com/items?itemName=rioj7.command-variable

Is it possible to pass arguments to a task in Visual Studio Code

Here's an example of my tasks.json:
{
"version": "0.1.0",
"tasks": [
{
"taskName": "test",
"suppressTaskName": true,
"command": "python",
"args": [
"tests/brewer_tests.py"
],
"isTestCommand": true
}
]
}
I can run this with shift+cmd+alt+b. I can also run it with alt+t, and choose it from the menu. Is it possible to pass additional arguments in that menu? e.g.
And you could build it into your task like so:
{
"version": "0.1.0",
"tasks": [
{
"taskName": "test",
"suppressTaskName": true,
"command": "python",
"args": [
"tests/brewer_tests.py",
$arg1 # would resolve to "ARG1"
],
"isTestCommand": true
}
]
}
Or something similar?
I used the solution from this answer until now, but since Visual Studio Code has now an official support for task prompts I will add it as an answer here.
In your tasks.json file, you add the key inputs next to your tasks. This key contains an array with all possible parameters. Note that not every task has to use all of these inputs.
All of these inputs have an id, which you will use to reference the input in your task.
Now, in the task you only need to add ${input:myInputId} whereever you need the parameter.
Example:
{
"version": "2.0.0",
"tasks": [
{
"label": "Echo param",
"type": "shell",
"command": "echo ${input:param1}",
"problemMatcher": []
},
{
"label": "Echo without param",
"type": "shell",
"command": "echo Hello",
"problemMatcher": []
},
],
"inputs": [
{
"id": "param1",
"description": "Param1:",
"default": "Hello",
"type": "promptString"
},
]
}
The task Echo param will open a prompt, which lets you input a string value and it will then print this value. The task Echo without param will simply print "Hello".
Here's what is working for me for now - using this to run a golang snippet with custom arguments.
If you add a keyboard mapping to this, the process is very straightforward.
So far tested this only under Windows - linux version is commented out for that reason
{
"label": "runwithargs",
"type": "shell",
"windows": {
"options": {
"shell": {
"executable": "powershell.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command"
]
}
},
"command": "",
"args": [
{ "value": "$cmdargs = read-host 'Enter command line arguments';", "quoting": "weak"},
{ "value": "go run ${file} $cmdargs", "quoting": "weak"}
]
},
/*"linux": {
"command": "echo 'Enter command line arguments: '; read cmdargs;",
"args": [ "go run ${file} $cmdargs" ]
},*/
"presentation": {
"panel": "dedicated",
"focus": true
}
}
Regarding Input variables, VSCode 1.43 (Feb. 2020) adds a new feature:
promptString Password Input
The "promptString" "input" type can have "password": true, which will cause the quick input that shows to obscure the typed content like a password.