How to trigger activation of the vscode markdown extension - visual-studio-code

In my VS Code extension I have some code that uses the built in Markdown extension. I capture a reference to it by registering as a markdown plugin and putting the following code at the end of my extension's activate method.
return {
extendMarkdownIt(mdparam: any) {
return md = mdparam;
}
};
Markdown calls this when it activates.
Generally this is not a problem. Most of the use cases for my extension involve a markdown file already loaded into the active editor, and the loading of this file triggers activation of the markdown extension.
However there are some legitimate use cases in which this is not so.
I need to programmatically trigger activation of the markdown extension. Some of these cases involve having a different kind of file open in the active editor so loading a markdown file into it is not an acceptable option.
Some potential strategies:
Change the language mode. There is a command workbench.action.editor.changeLanguageMode but no documentation. I tried
vscode.commands.executeCommand('workbench.action.editor.changeLanguageMode', 'md');
but this triggers the UI
so I tried a pattern I've seen in the parameters of other commands and added , true. This suppressed the UI but doesn't seem to work.
Load a markdown file into a new editor then close it again. This should work, but it's ugly.
Put something in the contributions section of my extension that changes the activation trigger for the markdown extension so that it is triggered by the other file types on which my extension operates.
Of these options my favourite would be 3 but I don't even know whether this is even possible. Option 1 is hampered by the crappy (in many cases non-existent) documentation for vscode internal commands.

Option 1 it is. If anyone knows how to do option 3 please tell, the solution below is a ghastly hack.
It is possible to trigger activation of the Markdown extension by changing the document language of any open editor to markdown. In the event that there are no open editors a document with the markdown language set can be created in memory and loaded into an editor.
If VS Code is busy loading extensions activation can take several hundred milliseconds so the best thing to do is watch the variable into which markdown-it is captured.
The variable md is a global (global to my extension, not the whole of VS Code) into which a reference is acquired as shown in the question.
let ed = vscode.window.activeTextEditor;
if (ed) {
let lid = ed.document.languageId;
if (lid !== "markdown") {
vscode.languages.setTextDocumentLanguage(ed.document, "markdown").then(
function waitForMd() {
if (md) {
vscode.languages.setTextDocumentLanguage(ed!.document, lid);
} else {
setTimeout(waitForMd, 100);
}
}
);
}
} else {
vscode.workspace.openTextDocument({ language: "markdown" }).then(doc => {
vscode.window.showTextDocument(doc).then(
function waitForMd() {
if (md) {
vscode.commands.executeCommand("workbench.action.closeActiveEditor");
} else {
setTimeout(waitForMd, 100);
}
});
});
}
Once the capture completes we can restore the true language or close the editor as appropriate. To be realistic the second case (no active editor) is unlikely because my own extension won't activate until you load something. At any rate it works stably now. The larger project is progressing nicely.

Related

Get notification in a VS Code extension when the Python interpreter is changed

I am writing a VS Code extension that depends on the currently set Python interpreter. When I change the Python Interpreter via the VS Code UI, the extension needs to refresh and get the latest Python path (mainly to show the right environment settings in the TreeView). For now, I have a refresh button in my custom TreeView that I need to press after selecting a different Python interpreter.
However, this is a second manual step. Is there a way to get a notification in my extension, when a user changes the Python Interpreter, e.g., an event the extension can listen to?
I only found VS Code's Activation Events, but it doesn't look like this would help. I didn't find any other events that get triggered after the command python.setInterpreter is executed
Finally found it. The right config to watch for is python.defaultInterpreterPath
vscode.workspace.onDidChangeConfiguration(event => {
let affected = event.affectsConfiguration("python.defaultInterpreterPath");
if (affected) {
doSomething();
}
});
To support the usingNewInterpreterStorage case (default today), add:
const extension = vscode.extensions.getExtension('ms-python.python')!;
await extension.activate();
extension.exports.settings.onDidChangeExecutionDetails((event: any) => {
doSomething();
});

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.

Error handling in extensions to visual studio code

Can someone point me to best practices for error handling in a Visual Studio Code extension?
I'm writing an extension in TypeScript that contributes a debugger. I want to log unexpected behavior, sometimes as information to the user explaining that something didn't go right, sometimes to create a trail for debugging, but certainly not to fail silently. Using console.log or console.error shows up in the debug output when I am debugging the extension, but I can't find it when the extension is installed. Do I have to open an output channel specifically for my extension and write everything there? Should I be throwing up showInformationMessage and showErrorMessage windows? Should I just be throwing exceptions and hope that code will do the right thing?
In my extension I use two ways for feedback. One is an output channel for errors produced by an external process that I'm using for the work.
Create the channel in your activation method:
outputChannel = window.createOutputChannel("ANTLR4 Errors");
and push output to it whenever you have something:
} catch (reason) {
outputChannel.appendLine("Cannot parse sentence generation config file:");
outputChannel.appendLine((reason as SyntaxError).message);
outputChannel.show(true);
return;
}
The other one is what you already considered:
if (workspace.getConfiguration("antlr4.generation").mode === "none") {
void window.showErrorMessage("Interpreter data generation is disabled in the preferences (see " +
"'antlr4.generation'). Set this at least to 'internal' to enable debugging.");
return null;
}
which is for messages I create in the extension and that users need to see and take seriously.

How to prevent VS Code from putting '{' on new line in C++ formatting?

If I write some code
void function() {
....
}
when I format the entire page using Shift+Alt+F, it becomes
void function()
{
....
}
How do I prevent that initial opening bracket from going to a new line?
Assuming you're using the MS C++ extension, these are the docs you're after. In > short, you'd need to either:
change C_Cpp.clang_format_fallbackStyle to one of: LLVM, Google, Chromium, > Mozilla, WebKit - and see if one matches your preferences.
find/make a custom .clang-format file
see clang-format docs for more details: > https://clang.llvm.org/docs/ClangFormatStyleOptions.html
https://www.reddit.com/r/vscode/comments/9rqj02/prevent_vscode_from_putting_c_curly_braces_on_new/

check the source of activation of extension in visual studio code

I'm developing an extension for visual studio code. My extension has several activation events. So in the activate call back how I can differentiate the source of activation? for ex., Extension get activate if a workspace contains a specific folder or if a command is given. In activate call back I want to execute different initialization for different activation. Is there any API to get this info?
Ex:
In package.json two activation events are given by
...
"activationEvents": [
"workspaceContains:foo",
"*"
],
...
In the extension.ts file the corresponding activate callback will be defined.
...
export function activate(context: ExtensionContext): any {
...
}
...
In the above scenario, activate() will be called in one of the 2 events:
If vscode opens.
If a folder is opened and contains foo file in the root directory.
what I want is like this:
export function activate(context: ExtensionContext): any {
if(/*activated by "*" event*/) {
Init1();
}
else if(/*activated by "workspaceContains" event*/) {
Init2();
}
}
This is just a pseudo code. But This is what the whole point is.
As lined out in the comments there is no way to differentiate between the two activation events. In fact the activation is done by matching one of the patterns in package.json. Other than for documents there is no indication which pattern was actually matched. That's probably too fine grained, hence I have doubts that creating a feature request for that will have a chance.