I try to open a document from a Hover in a VSCode Extension.
The Hover appears, the link is shown and also the URI, but when I click, nothing happens. There is an output in the Debug Console, that the command is unknown in the Developer Tools Console.
What I am doing wrong? Here is the code, a little bit simplified
context.subscriptions.push(
vscode.languages.registerHoverProvider({pattern: '**/*.{ttp,tts}'}, {
provideHover(document, position, token) {
const linkPosition = new vscode.Position(10, 1);
const range = new vscode.Range(position, position);
const opts: vscode.TextDocumentShowOptions = {
selection: range,
viewColumn: vscode.ViewColumn.Beside
};
const workspace = vscode.workspace.workspaceFolders?.find(e => e.uri.fsPath.endsWith("workspace"));
const uri = vscode.Uri.file(`${workspace?.uri.path}/_global.tt/ercdata/ttc.properties`);
const args = [{ uri: uri , options: opts}];
const stageCommandUri = vscode.Uri.parse(
`command:window.showTextDocument?${encodeURIComponent(JSON.stringify(args))}`
);
let link = new vscode.MarkdownString(`[Open...](${stageCommandUri})`);
link.isTrusted = true;
let hover: vscode.Hover = {
contents: [link]
};
return hover;
let x = properties.getHoverFor(document, position, path.basename(document.uri.fsPath).replace(".tts","").replace(".ttp","").toLowerCase());
return x;
}
}));
Here is how the Hover renders:
Here is the output of the dev console:
You should use a true command like vscode.open as documented in this article, or your own command.
window.showTextDocument alone is an extension API.
Lex Li pointed me into the right direction, thank you.
Wrapping the openTextDocument task into my own command and adressing this command from the Hover solves the problem:
context.subscriptions.push(vscode.commands.registerCommand('estudio.internal.open', (uri: vscode.Uri, options: vscode.TextDocumentShowOptions) => {
logger.info("Opening a document");
vscode.window.showTextDocument(uri, options);
}));
Than composing the Hover use
const stageCommandUri = vscode.Uri.parse(
`command:estudio.internal.open?${encodeURIComponent(JSON.stringify(args))}`
did it.
Related
I'm working on a custom language extension and I'm having issues with how to show functions for a variable.
I'm importing my language in the form of json, so i've created a typescript-file that i import into my extensions.ts:
export interface CustomIntellisense {
text: string;
help: string;
}
const data = [{
"text": "Void.String",
"help": "<h1>String String()</h1><p>Default constructor.<code>String something;</code></p>"
},
{
"text": "String.toInteger",
"help": "<h1>Integer toInteger()</h1><p>Converts a String to its numeric representation."
},
{
"text": "Void.Integer",
"help": "<h1>Integer Integer()</h1><p>Default constructor.</p>"
}];
export let json: CustomIntellisense[] = data;
My idea here is that the elements containing "Void" in text gets created as a variable, while the other element gets added as a method.
const provider1 = vscode.languages.registerCompletionItemProvider({ language: 'myLanguage', scheme: 'file' }, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
let items: vscode.CompletionItem[] = [];
let re = /\"/gi;
json.forEach(element => {
const item = new vscode.CompletionItem(element.text.split('.')[1]);
item.insertText = new vscode.SnippetString(element.help);
const markdownDocumentation = new vscode.MarkdownString();
markdownDocumentation.supportHtml = true;
markdownDocumentation.appendMarkdown(element.help);
item.documentation = markdownDocumentation;
if (element.text.includes('Void.')) { //If text includes Void this should be a variable
item.kind = vscode.CompletionItemKind.Variable;
}
else {
item.kind = vscode.CompletionItemKind.Method;
}
items.push(item);
});
return items;
}
});
The items gets added to the view, but I can't figure out how to 'filter' what is shown.
The official example on how to achieve this can be found here:
https://github.com/microsoft/vscode-extension-samples/blob/main/completions-sample/src/extension.ts
But this only explains how to filter based on the text/name, and i cant filter this specifically for each variableName i use.. If i somehow could detect what kind of Variable i'm working on I could possibly create a function that fetches if its a String/Int, then parse through my file and add methods in my 2nd CompletionItemProvider. But I havent found any good way of deciding the type of variable..
What i want is this:
If i click ctrl+space i want toInteger() to be the only thing that shows up, but instead it lists up everything all the time:
Anyone have a clue how to achieve this?
I would like to make a control similar to the used by github copilot. I mean highlighting the proposed text. Live share extension uses a very similar approach. What is the name of this control?
Control in live preview extension:
Control in copilot extension:
I guess it could be TextEditorDecorationType? However, I do not know how to style it so that the author is absolutely positioned :/
You can create a similar experience using Text Editor Decorators. These decorators allow you to use custom style patterns for any text in a document (including foreground and background colors).
The text highlighting examples that you have visualized above, are simply adding a a background color to a span of text that has been selected by a user, or suggested by an extension.
As an example: if you wanted to add custom highlighting for console.log:
Then you could use the following:
import * as vscode from 'vscode'
const decorationType = vscode.window.createTextEditorDecorationType({
backgroundColor: 'green',
border: '2px solid white',
})
export function activate(context: vscode.ExtensionContext) {
vscode.workspace.onWillSaveTextDocument(event => {
const openEditor = vscode.window.visibleTextEditors.filter(
editor => editor.document.uri === event.document.uri
)[0]
decorate(openEditor)
})
}
function decorate(editor: vscode.TextEditor) {
let sourceCode = editor.document.getText()
let regex = /(console\.log)/
let decorationsArray: vscode.DecorationOptions[] = []
const sourceCodeArr = sourceCode.split('\n')
for (let line = 0; line < sourceCodeArr.length; line++) {
let match = sourceCodeArr[line].match(regex)
if (match !== null && match.index !== undefined) {
let range = new vscode.Range(
new vscode.Position(line, match.index),
new vscode.Position(line, match.index + match[1].length)
)
let decoration = { range }
decorationsArray.push(decoration)
}
}
editor.setDecorations(decorationType, decorationsArray)
}
Reference Link
Let's say i have following custom plugin:
const webpack = require('webpack');
const path = require('path');
const pluginName = 'TestWebpackPlugin';
class TestWebpackPlugin {
constructor(opts) {
this.options = opts || {};
}
apply(compiler) {
const options = this.options
compiler.hooks.compilation.tap('TestWebpackPlugin', (compilation) => {
compilation.hooks.needAdditionalPass.tap('TestWebpackPlugin', () => false)
compilation.hooks.processAssets.tap(
{
name: 'TestWebpackPlugin',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_DERIVED
},
(assets) => {
// this new asset will also be minimized if mode = production
// the question is: how to make this new asset ignored by minimizer?
compilation.emitAsset(
'newfile',
new webpack.sources.RawSource('console.log("test content")')
);
}
);
});
}
}
module.exports = TestWebpackPlugin
the question is: how to make this new asset ignored by minimizer?
I found the question while searching for more information on the emitAsset method (how to write in UTF-8).
I am rewriting a Webpack 4 plugin (in an Angular context) with this new syntax, following the example given at https://webpack.js.org/contribute/writing-a-plugin/, and when I write the file at the given Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE stage, I find out that:
I can give a relative path, like: ./i18n/${fileName}.json
The written files are not minimized
Somebody can help me how to custom autocomplete for ace editor?
I need to display the emoji images such as below:
This editor is work well for me, but i need to insert the emoji images to the result of autocomplete.
var editor = ace.edit('editor');
editor.setTheme('ace/theme/github');
editor.getSession().setMode('ace/mode/markdown');
editor.$blockScrolling = Infinity; //prevents ace from logging annoying warnings
editor.getSession().on('change', function () {
draceditor.val(editor.getSession().getValue());
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
});
// Ace autocomplete
var emojiWordCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
var wordList = emojis; // list emojis from `atwho/emojis.min.js`
var obj = editor.getSession().getTokenAt(pos.row, pos.column.count);
var curTokens = obj.value.split(/\s+/);
var lastToken = curTokens[curTokens.length-1];
if (lastToken[0] == ':') {
console.log(lastToken);
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word.replace(':', '') + ' ',
meta: 'emoji' // this should return as text only.
};
}));
}
}
}
editor.completers = [emojiWordCompleter]
my bad idea, i try with this meta: '<img src="/path/to/emoji.png">', but of course it can't be work.
Any idea how to solve this? Thank so much before..
There is no built in way to do this.
You can create a custom renderer similar to https://github.com/c9/c9.ide.language.core/blob/bfb5dd2acc/completedp.js#L44, or modify https://github.com/ajaxorg/ace/blob/master/lib/ace/autocomplete/popup.js and create pull request to ace.
I am trying to make Ace Editor support autocomplete for my own query language.
The query itself is something like below
city:newyork color:red color:blue
In above case, I expect the user can see 'city' and 'color' when typing 'c'. And after he selects 'color', he can directly see the two options 'red' and 'blue' in the suggestions list.
I checked all arguments of getCompletions: function(editor, session, pos, prefix, callback). But still cannot figure out the better way to do this. Any suggestion will be appreciated.
It's not possible directly or through ace editors default auto complete.
But I have sample code which may full fill your requirement.
Step-1:
You have to create editor object and set options:
ace.require("ace/ext/language_tools");
var editor = ace.edit('div_id');
editor.setTheme("ace/theme/textmate");
editor.getSession().setMode("ace/mode/yaml");
editor.getSession().setTabSize(4);
editor.getSession().setUseSoftTabs(true);
editor.setDisplayIndentGuides(true);
editor.setShowInvisibles(true);
editor.setShowPrintMargin(false);
editor.setOption("vScrollBarAlwaysVisible", true);
editor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
});
var EditorWordCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
getWordList(editor, session, pos, prefix, callback);
}
}
var getWordList = function(editor, session, pos, prefix, callback) {
var wordList = [];
if(prefix === 'T') {
wordList.push('List of tasks');
}
wordList = $.unique(wordList);
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word
};
}));
}
Please change it as per you're requirements.