Can i pass arguments to command in contributes block? - visual-studio-code

I would like to reusing command with some arguments.
I found key binding can do this with "args" property:
{
"key": "cmd+k 8",
"command": "editor.action.insertSnippet",
"when": "resourceLangId == 'markdown'",
"args": {
"name": "Insert bold text"
}
}
so i try to write my package.json/contributes/menus in a similar way and it didnt work:
"commands": [
{
"command": "extension.sayHello",
"title": "Say Hello"
}
],
"menus": {
"editor/context": [
{
//menu one
"command": "extension.sayHello",
"group": "navigation#1",
"args": {
"text": "Say Hello 1!"
}
},
{
//menu two
"command": "extension.sayHello",
"group": "navigation#2",
"args": {
"text": "Say Hello 2!"
}
}
]
}
I would like to pass "text" to command handler function.
Are there any feature to archive similar result?

This is an old question, founded it on Github firstly, but i wanted to share some info that i actually founded within many resources and code-analysis:
So, even now, in a date when i writing it down here, there is still no normal way for making it in package.json... Like, at all...
But, by looking at some other extensions, i see that some of them are actually founded another way for making it working:
To do this, we need to look at the vscode.commands.registerCommand command.
function commands.registerCommand(command: string, callback: (...args: any[]) => any, thisArg?: any): vscode.Disposable
That means, we can use third parameter to actually send some data.
As an example:
package.json:
"contributes": {
...
"menus": {
"view/title": [
{
"command": "extension.addEntryOne",
"when": "view == extension",
"group": "navigation"
},
{
"command": "extension.addEntryTwo",
"when": "view == extension2",
"group": "navigation"
}
]
},
"commands": [
{
"command": "extension.addEntryOne",
"title": "Add entry One",
"icon":"$(diff-insert)"
},
{
"command": "remospace.addEntryTwo",
"title": "Add entry Two",
"icon":"$(diff-insert)"
}
]
...
}
extension.ts:
//
//Activation part before
//
let Execution = function(this: any){
console.log(this)
}
let entryOne = vscode.commands.registerCommand('extension.addEntryOne', Execution,{from:'one'});
let entryTwo = vscode.commands.registerCommand('remospace.addEntryTwo', Execution,{from:'one'});
context.subscriptions.push(entryOne,entryTwo);
In this case, we can bypass issue when we need to do same thing with different args. Yes, this may not be the best solution to do it, but at least this is one of it.

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 order inline view toolbar icons?

In my authoring of a VS Code extension, I'd like to have "+" icon shown to the right of refresh icon. However, the ordering in the package.json does not seem to represent the order rendered. I always get the add icon to the left of refresh icon.
Here is a snippet of the view definition:
{
"commands": [
{
"command": "refresh-jobs",
"title": "Refresh",
"icon": {
"light": "resources/light/refresh.svg",
"dark": "resources/dark/refresh.svg"
}
},
{
"command": "add-job",
"title": "Add",
"icon": {
"light": "resources/light/add.svg",
"dark": "resources/dark/add.svg"
}
},
],
...
"view/item/context": [
{
"command": "refresh-jobs",
"group": "inline",
"when": "viewItem == jobgroup"
},
{
"command": "add-job",
"group": "inline",
"when": "viewItem == jobgroup"
},
]
}
Any help? Thanks!
I found this old issue: Add custom ordering to title menu items. which suggest doing something like:
There is way to define the order and I am surprised we haven't
properly documented that... What you can do is adding an order to the
group-attribute like so group: name#number. In your case
{
"command": "md-shortcut.toggleBold",
"when": "editorLangId == 'markdown'",
"group": "2_markdown_1#1"
}
I see it here: menu example The #n syntax is used there to order menu entries but the issue I cited above seems to imply that it will also order icons in a title bar. Try this:
"view/item/context": [
{
"command": "refresh-jobs",
"group": "inline#1",
"when": "viewItem == jobgroup"
},
{
"command": "add-job",
"group": "inline#2",
"when": "viewItem == jobgroup"
},
]
"group": "inline#1", note the #1
Let me know if it works for you.

Unable to create menu with contributes.menu

I am unable to create a menu using the documentation at the link below for contributes.menu. Actually, I was able to create one menu item, but could not create a second one. The code excerpt is from my package.json on Windows 10 using VS Code 1.37.0.
So my question is, can someone show me an example of adding two menu items?
-TIA
"contributes": {
"menus": {
"editor/title": [{
"title": "Underline Text",
"when": "editorHasSelection",
"command": "macros.underline",
"alt": "markdown.showPreviewToSide",
"group": "MyGroup#1"
}]
},
"languages": [
https://code.visualstudio.com/api/references/contribution-points#contributes.menus
Already tried the above code.
Here is an example package.json, based on the one in the tutorial, that creates two menu items:
{
...
"activationEvents": [
"onCommand:extension.helloWorld",
"onCommand:extension.helloAnotherWorld"
],
"contributes": {
"commands": [
{
"command": "extension.helloWorld",
"title": "Hello World"
},
{
"command": "extension.helloAnotherWorld",
"title": "Hello Another World"
}
],
"menus": {
"editor/title/context": [
{
"command": "extension.helloWorld"
},
{
"command": "extension.helloAnotherWorld"
}
]
}
},
...
}

How do I hide a command in the palette menu from my extension in VS Code

I am building a VS Code extension starting from this page. Now I want to hide in the palette menu the command extension.timerStart after I run it. I have read this page, didn't helped. I have the code bellow for package.json. How do I make the varFromMyExtension===false part work?
"contributes": {
"commands": [
{
"command": "extension.timerStart",
"title": "Timer Start"
}
],
"menus": {
"commandPalette": [
{
"command": "extension.timerStart",
"when": "varFromMyExtension===false"
}
]
}
I think it is not possible to access variables from your extension directly in a when clause. However you can access any configuration of the settings.json.
From the docs (at the bottom of the chapter):
Note: You can use any user or workspace setting that evaluates to a boolean here with the prefix "config.".
So when your extension contributes a boolean configuration called varFromMyExtension you should be able to use it in the when clause. This configuration then can be manipulated programmatically, too.
So your package.json would probably contain something like this (not tested):
"contributes": {
"commands": [
{
"command": "extension.timerStart",
"title": "Timer Start"
}
],
"menus": {
"commandPalette": [
{
"command": "extension.timerStart",
"when": "!config.myextension.varFromMyExtension"
}
]
},
"configuration": {
"type": "object",
"title": "Indicates whether ...",
"properties": {
"myextension.varFromMyExtension": {
"title": "My title.",
"description": "My description",
"type": "boolean",
"default": false,
"pattern": "(true|false)"
}
}
}
}
But bare in mind that the user can see and edit this setting, too.

How to bind one key to multiple commands in VSCode

I'm trying to make the key Ctrl+UpArrow execute both commands
cursorUp and
scrollLineUp.
I was hoping that this would work, but it doesn't:
{
"key": "ctrl+up",
"command": ["cursorUp", "scrollLineUp"], // This doesn't work
"when": "editorTextFocus"
}
How do I do that in VSCode?
This is currently not possible, but the corresponding feature request is tracked here. However you should take a look to the macros extension. It enables you to chain different commands to a single custom command. This custom command then can be bound to a hotkey.
In your case you could add this to your settings.json:
"macros": {
"myCustomCommand": [
"cursorUp",
"scrollLineUp"
]
}
And then add your custom hotkey to the keybindings.json:
{
"key": "ctrl+up",
"command": "macros.myCustomCommand"
}
There's a new way to achieve this without an extension:
Run "Tasks: Open User Tasks" command to create or open a user level tasks file.
Define commands as separate tasks, like so:
{
"version": "2.0.0",
"tasks": [
{
"label": "ctrlUp1",
"command": "${command:cursorUp}"
},
{
"label": "ctrlUp2",
"command": "${command:scrollLineUp}"
},
{
"label": "ctrlUpAll",
"dependsOrder": "sequence",
"dependsOn": [
"ctrlUp1",
"ctrlUp2"
],
"problemMatcher": []
}
]
}
In your keybindings.json:
{
"key": "ctrl+up",
"command": "workbench.action.tasks.runTask",
"args": "ctrlUpAll",
"when": "editorTextFocus"
}
("ctrlUpNNN" label format chosen for readability, task labels can be anything).