Monaco-editor: Custom Worker for my own language

Created on 23 Feb 2019  路  5Comments  路  Source: microsoft/monaco-editor

Hello,

I want to add a custom language worker, I don't want to use the existing ones for ts,js, html...,I want to create a new worker for my own language which will communicate with my language service, also I don't want to use monaco-languageclient because it uses an old version of monaco.
_any help will be appreciated!_

Thanks!

All 5 comments

You have 2 issues with the same content

What are you trying to do with the worker? Provide language services? Highlighting? Something else?

There's pretty good documentation
https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html

You can also look at how monaco-languageclient is implemented and do the same thing

To elaborate on what @masad-frost said, https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html gives you several methods to register your own providers for certain editor functionalities, such as

  • registerCodeLensProvider
  • registerCompletionItemProvider
  • registerDocumentFormattingEditProvider
  • ...

These providers return a ProviderResult:

A provider result represents the values a provider, like the HoverProvider, may return. For once this is the actual result type T, like Hover, or a thenable that resolves to that type T. In addition, null and undefined can be returned - either directly or from a thenable.

You register your own providers and return a promise, ie. return the actual provider result later. This also lets you query a web worker and return the result once the web worker is done. This approach leaves it up to you how you implement the web worker.

Here's a simple example you can try in the playground: for a language named mySpecialLanguage.

// Create a simple web worker
const workerScript = `
self.onmessage=function(e) {
    console.log("Worker: Receiving message", e.data);
    const textUntilPosition = e.data;
    const data = {
        suggestions: [
            {
                label: "Foobar",
                kind: 25,
                detail: "Details for completion",
                insertText: "Message from webworker"
            }
        ]
    };
    postMessage({id: e.data.id, data: data, success: true});
}
`;
let blob;
try {
    blob = new Blob([workerScript], {type: 'application/javascript'});
} catch (e) { // Backwards-compatibility
    blob = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)();
    blob.append(workerScript);
    blob = blob.getBlob();
}
const worker = new Worker((window.URL || window.webkitURL).createObjectURL(blob));

// Handle messages from web worker
let id = 0;
/** @type {Map<string, {resolve: ()=>void, reject: ()=>void}>} */
const messageMap = new Map();
worker.onmessage = function(e) {
    console.log("Main: Receiving message", e.data);
    const promise = messageMap.get(e.data.id);
    if (promise) {
        messageMap.delete(e.data.id);
        if (e.data.success) promise.resolve(e.data.data);
        else promise.reject(e.data.data);
    }
}

// Register a new language
monaco.languages.register({ id: 'mySpecialLanguage' });

// Register a completion item provider that queries the web worker
monaco.languages.registerCompletionItemProvider("mySpecialLanguage", {
    provideCompletionItems(model, position, context, token) {
        const textUntilPosition = model.getValueInRange({startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column});
        const currentId = ++id;
        const promise = new Promise((resolve, reject) => {
            messageMap.set(currentId, {resolve, reject});
        });
        worker.postMessage({id: currentId, data: textUntilPosition});
        return promise;
    },
    resolveCompletionItem(model, position, item, token) {
        return item;
    }
})

// Create a new monaco editor
monaco.editor.create(document.getElementById("container"), {
    value: "// Example for a custom language with webworker\n// Try typing 'Foobar'\n",
    language: "mySpecialLanguage"
});

This approach also leaves it up to you to transfer any required data to thE web worker (such as the current editor content). See https://microsoft.github.io/monaco-editor/api/modules/monaco.editor.html#createwebworker

Thanks guys

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robclive picture robclive  路  3Comments

andreymarchenko picture andreymarchenko  路  3Comments

PinkyJie picture PinkyJie  路  3Comments

akosyakov picture akosyakov  路  3Comments

SoftTimur picture SoftTimur  路  3Comments