Is there anyway to check inactive terminalEditors in when arg in keybindings.json in VScode? - visual-studio-code

I want to createTerminalEditor if there is no terminalEditor opened yet.
Note: I'm talking about terminalEditor and not terminal.
So, I'm looking for a when arg which says something like editorAlreadyExists != terminalEditor, just like there is activeEditor which aceepts string of terminalEditor.
Is there anyway to achieve this?
Here is activeEditor example for reference, but I want to check if terminalEditor exists in all the already opened editors, not just a activeEditor.
{
"key": "ctrl+`",
"command": "workbench.action.createTerminalEditor",
"when": "activeEditor != terminalEditor"
},

I see that there is a when clause for:
terminalEditorFocus: true/false
which doesn't look like it would help except for the fact that it isn't in the list (via Developer: Inspect Context Keys) at all when there is no terminal editor open. So I thought maybe there was a keybinding when clause that could exploit this. But I tried all kinds of thing, like whether it was null or undefined or the empty string or neither true nor false, etc. but nothing worked. I think if the key terminalEditorFocus doesn't exist, then nothing at all is delivered to the keybinding resolver and it always fails.
You could file an issue asking for a specific terminalEditorExists sort of when clause.
There will be another way. There is a presently experimental api to access all the open tabs. See proposed api. So you could write an extension that checks all the open tabs and fires the workbench.action.createTerminalEditor command if none are a terminalEditor. It works right now in the Insiders Build, but when it will go final I don't know - it seems pretty solid now. Issue: Tab Model API.
const tabs = vscode.window.tabs;
const openTerminalEditor = tabs.some(tab => tab.viewId === 'terminalEditor'); // true/false
Then you could either set your own context key with setContext or run the command.

Related

VsCode Extension custom CompletionItem disables built-in Intellisense

I am working on a VsCode extension in that I want to provide custom snippets for code completion.
I know about the option of using snippet json files directly, however those have the limitation of not being able to utilize the CompletionItemKind property that determines the icon next to the completion suggestion in the pop-up.
My issue:
If I implement a simple CompletionItemProvider like this:
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
{scheme:"file",language:"MyLang"},
{
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
let item = new vscode.CompletionItem('test');
item.documentation = 'my test function';
item.kind = vscode.CompletionItemKind.Function;
return [item];
}
}
)
)
then the original VsCode IntelliSense text suggestions are not shown anymore, only my own. Should I just return a kind of an empty response, like
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
return [null|[]|undefined];
}
the suggestions appear again as they should. It seems to me that instead of merging the results of the built-in IntelliSense and my own provider, the built-in ones get simply overridden.
Question:
How can I keep the built-in IntelliSense suggestions while applying my own CompletionItems?
VsCode Version: v1.68.1 Ubuntu
I seem to have found the answer for my problem, so I will answer my question.
Multiple providers can be registered for a language. In that case providers are sorted
by their {#link languages.match score} and groups of equal score are sequentially asked for
completion items. The process stops when one or many providers of a group return a
result.
My provider seems to provide results that are just higher scored than those of IntelliSense.
Since I didn't provide any trigger characters, my CompletionItems were comteping directly with the words found by the built-in system by every single pressed key and won.My solution is to simply parse and register the words in my TextDocument myself and extend my provider results by them. I could probably just as well create and register a new CompletionItemProvider for them if I wanted to, however I decided to have a different structure for my project.

Using Chrome Dev Tools Code Folding Shortcuts

On the Settings > Preferences > Source we can enable Code Folding on the Chrome Dev. But I didn't find a way to use keyboard shortcuts to, eg. collapse all, etc. Did look for in the Shortcuts section window and in the Full Listings also, but no success. I'm assuming we can't do it on the current version. In case someone knows about it, I'll be very happy to know it too.
There's no such hotkey so try suggesting this feature on https://crbug.com.
Meanwhile you can add it manually:
make sure "code folding" is enabled in devtools settings (in the "Sources" group)
run this code in devtools-on-devtools (see the instruction below)
[
['Shift-Ctrl-[', 'fold'],
['Shift-Ctrl-]', 'unfold'],
['Shift-Ctrl--', 'foldAll'],
['Shift-Ctrl-=', 'unfoldAll'],
].forEach(([key, cmd]) => {
CodeMirror.keyMap['devtools-common'][key] = CodeMirror.commands[cmd];
});
close devtools-on-devtools
This will last only for the current devtools instance.
For convenience you can save the code in snippets and run it later from there or by typing the snippet name in the commands palette (Ctrl-P or Cmd-P hotkey).
How to open devtools-on-devtools:
Open devtools first and switch its Dock side in the menu to a detached (floating) window
in the now detached devtools press CtrlShifti or ⌘⌥i on MacOS,
which will open devtools-on-devtools in a new window
The top answer is great, but chrome devtools has been updated since to use CodeMirror 6, which requires a codeMirror instance to be passed to the functions:
CodeMirror.commands.foldAll();
Uncaught TypeError: Cannot read properties of undefined (reading 'operation')
at CodeMirror.commands.foldAll (foldcode.js:105:8)
at <anonymous>:1:21
line 104-109 from foldcode.js:
CodeMirror.commands.foldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
});
};
I could solve it by debugging a codemirror event to save the cm instance as a global variable (temp1), but I would appreciate if someone could have a better solution to this that can be automated.
Edit: I found the codeMirror instance at document.getElementsByClassName("CodeMirror")[1].CodeMirror, so a working solution is:
CodeMirror.commands.foldAll(document.getElementsByClassName("CodeMirror")[1].CodeMirror)
the shortcut setting still doesn't seem to work though.
(with
CodeMirror.keyMap["devtools-common"]["Ctrl-k"]=function()
{let {CodeMirror:instance}=
document.getElementsByClassName("CodeMirror")[1];
CodeMirror.commands.foldAll(instance);
};
)
Edit 2: oh, it just needed capital K, so "Ctrl-K". Now the shortcut works too. hurrah
btw i've commented on the folding feature's thread on chromium bugtracker to include this, because it is incredibly useful for skimming files while editing/reading. No response yet, idk if anyone's even paying attention to comments there anymore:
https://bugs.chromium.org/p/chromium/issues/detail?id=328431
CodeMirror 6 supports the folding shortcuts natively (per foldKeymap):
Ctrl-Shift-[ (Cmd-Alt-[ on macOS): Fold the lines that are selected, if possible.
Ctrl-Shift-] (Cmd-Alt-] on macOS): Unfold folded ranges on selected lines.
Ctrl-Alt-[: Fold all top-level foldable ranges.
Ctrl-Alt-]: Unfold all folded code.

contributes.menus: what are the possible variables for "when" action [duplicate]

VSCode 1.3 has added support for adding commands to context menus. Is there a way to identify whether a file or folder is clicked to open the explorer context menu?
"menus": {
"explorer/context": [
{
"when": "????",
"command": "extension.myCommand",
"group": "myGroup"
}
]
}
Also, is there a comprehensive(ish) list of expressions that might be checked in the when clause here?
You can use "when": "explorerResourceIsFolder".
I had to dig through the code to find it (I was actually writing up a response to say it didn't exist and enumerating the possible clause values when I saw it).
As of v1.10.1:
config.<any_config_path_here>
editorIsOpen
explorerResourceIsFolder
explorerViewletFocus
explorerViewletVisible
filesExplorerFocus
globalMessageVisible
inDebugMode
inQuickOpen
inZenMode
listFocus
openEditorsFocus
resource (Uri information: path, query, scheme, etc)
resourceFilename
resourceLangId
resourceScheme
scmProvider
textCompareEditorVisible
I've submitted an issue to improve the documentation for this.
Regarding obtaining a comprehensive list of context keys: in recent VSCode versions, there's a Developer: Inspect Context Keys command. After executing the command, it lets you pick a UI element:
After that, the dev console opens, and you can expand the logged object that contains a full list of context keys and their current values in this "scope":
https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts
is file: "when": "!explorerResourceIsFolder"
is dir: "when": "explorerResourceIsFolder"
You can get the list of language ids like this...
vscode.languages.getLanguages().then(l => console.log('languages', l));
I still haven't figured out how to determine if the item that was right clicked is a directory. If someone figures it out please let me know.
A write up about the feature is here. But basically:
the when is the same as the keybindings-when and can use the same keys
the when can use two new keys resourceScheme and resourceLangId which are available without an editor - think of the explorer context
menu
the when can be a boolean configuration value, e.g config.editor.lineNumbers
My menu:
"menus":{
"explorer/context": [
{
"when": "resourceLangId == sql",
"command": "extension.myCmd"
}
]

How can I configure multiple formatters to run in a sequence on save in VSCode?

I am working on a Haskell project that must be formatted by both:
stylish-haskell (for import reordering)
brittany (for general formatting)
I can set the single default formatter for a language:
"[haskell]": {
"editor.defaultFormatter": "MaxGabriel.brittany"
}
or I can select one from a list using editor.action.formatDocument.multiple ("Format Document With... in the command palette).
But I need to run both of them, one after the other, on save. As of right now, I can only run the single default formatter on save. The order doesn't matter in this case, but it could in more general cases.
I've tried setting editor.defaultFormatter to a list of formatters (this didn't work, as expected) and built a local extension that calls editor.action.formatDocument.multiple with various arguments, which just brings up a drop-down list of available formatters to choose from.
How can I run both formatters sequentially on save?
I don't think this is really a use case that is officially supported, but you could possibly work around it by having an extension do the following:
disable "editor.formatOnSave" for Haskell
register a callback for vscode.workspace.onDidSaveTextDocument, in which you:
set "editor.defaultFormatter" to the first formatter using the WorkspaceConfiguration API
call "editor.action.formatDocument"
set "editor.defaultFormatter" to the second formatter
call "editor.action.formatDocument" again
Of course, this only covers formatOnSave formatting, not formatOnPaste or formatOnType.
It's a bit late but, for newcomers, you can also use one extension that is already created... and it's thanks to all the answers of this post, by the way.
See Multi Formatter
So you can just add the formatters you want to run in the settings.json or the *.code-workspace settings like this:
{
"[haskell]": {
"editor.defaultFormatter": "Jota0222.multi-formatter",
"editor.formatOnSave": true
"multiFormatter.formatterList": [
"vigoo.stylish-haskell",
"MaxGabriel.brittany"
],
}
}
With that configuration, stylish-haskell will run first and Britanny will run just after once you save the changes.
P.S.: I'm indeed the author of the solution. I'm not aiming to do any promotion, it's just an implementation of the answers above. So I'll like to thank the people that answered before me.
Also, the extension is open sourced, feel free to check the code and contribute on GitHub
Last thoughts: look at Run on Save extension and execute your formatters not as extensions but as scripts.
Previous edit:
If your formatter doesn't contribute a command (see discussion in comments for some that do) as it appears brittany does not, try something like this for its task:
{
"label": "brittany format step",
"type": "shell",
"command": "brittany ${file}",
"problemMatcher": []
}
From Gama11's answer of creating a VSCode extension:
The following code specifies the formatter and then formats the code.
const config = vscode.workspace.getConfiguration('editor', vscode.window.activeTextEditor?.document);
await config.update('defaultFormatter', 'MaxGabriel.brittany');
await vscode.commands.executeCommand('editor.action.formatDocument');
Therefore, the answer is:
const config = vscode.workspace.getConfiguration('editor', vscode.window.activeTextEditor?.document);
const formatters = ['MaxGabriel.brittany', 'ms-python.python'];
formatters.forEach(async formatter => {
await config.update('defaultFormatter', formatter);
await vscode.commands.executeCommand('editor.action.formatDocument');
});

VSCode extension: disable repeating things in code completion

I am creating a language extension for VSCode using Java and the LSP4J library. It is something like this.
But I have a problem - if the user presses Ctrl+Space, and the language server returns an empty list, VSCode will still offers its options - things that are already in the code. How can I get it to display something like "No suggestions" instead?
The text-based completion you're seeing there can be disabled with the "editor.wordBasedSuggestions" setting.
Extensions can change the default value of a setting for a particular language by contributing configurationDefaults in package.json:
"contributes": {
"configurationDefaults": {
"[lang]": {
"editor.wordBasedSuggestions": false
}
}
}
Where lang is the ID of the language in question.
If the language server sends back an empty list you could add an artificial entry with text: "No suggestions" to the completion list.