Hi,
I'm wondering if it's possible to provide dynamic code completion depending on the input.
For example, I want to create a custom completion for jQuery style code like this:
$("button")
Let's assume I load a custom TS definition file that has a definition for the type button.
I want to be able to register a code completion provider that will analyze the text, realize the $ function refers to a button, and provide the button members from the definition file.
I can then do the same logic for other types of course, and completion for the following samples will work as well:
$("image")
$("input")
Is this possible in any way?
Thanks!
Yes, please see registerCompletionItemProvider. There is even a playground example for that: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
Thanks! I'm aware of the API and the example, but I don't see how can I get an AST to do better analysis on what the user wrote, or how can I provide back a type so that intellisense will continue to work on the returned completion items.
I looked at the typescript worker code, and it seems like I may need to create my own worker and somehow use language services to map custom code to types ($('button') -> button type).
Does that make any sense?
Thanks, I know it's probably a bizarre question and I appreciate the help :)
You can use the builtin TS extra libs support if your strings are known upfront. If you need to do some custom runtime logic, you're going to need to implement something custom.
e.g. paste this at https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults
// Add additonal d.ts files to the JavaScript language service and change.
// Also change the default compilation options.
// The sample below shows how a class Facts is declared and introduced
// to the system and how the compiler is told to use ES6 (target=2).
// validation settings
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false
});
// compiler options
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true
});
// extra libraries
monaco.languages.typescript.javascriptDefaults.addExtraLib([
'declare function $(arg:"input"): HTMLInputElement;',
'declare function $(arg:"button"): HTMLButtonElement;',
].join('\n'), 'filename/facts.d.ts');
var jsCode = [
'var input = $("input");',
'var button = $("button");',
].join('\n');
monaco.editor.create(document.getElementById("container"), {
value: jsCode,
language: "javascript"
});
Thanks for the reply, it's getting closer to what I'm looking for.
I think I wasn't clear in my first post, I apologize for that.
The argument for $ is not known at compile time, just like jQuery.
Meaning, the function can accept an id for an element, for example:
$('button1'), $('button2'), $('image1').
I have a map that maps button1 to a button type, button2 to a button type, image1 to an image type etc.
Let's assume I also have a TS definition file, with all the types.
I want to be able to tell the code completion engine, at runtime, that the return value for $('button1') is of type button.
Can I maybe do what you described with addExtraLib and call it at runtime, adding multiple declarations for all the ids I have whenever the ids list changes? Or is there a better way to do it?
Thanks again for all the help, it's much appreciated.
Most helpful comment
Thanks for the reply, it's getting closer to what I'm looking for.
I think I wasn't clear in my first post, I apologize for that.
The argument for
$is not known at compile time, just like jQuery.Meaning, the function can accept an id for an element, for example:
$('button1'),$('button2'),$('image1').I have a map that maps button1 to a button type, button2 to a button type, image1 to an image type etc.
Let's assume I also have a TS definition file, with all the types.
I want to be able to tell the code completion engine, at runtime, that the return value for
$('button1')is of type button.Can I maybe do what you described with
addExtraLiband call it at runtime, adding multiple declarations for all the ids I have whenever the ids list changes? Or is there a better way to do it?Thanks again for all the help, it's much appreciated.