CodinGame / monaco-vscode-api

VSCode public API plugged on the monaco editor
MIT License
214 stars 29 forks source link

Problems Loading A custom theme #460

Closed mep-bsw closed 2 weeks ago

mep-bsw commented 2 weeks ago

as per new requirements, i need to use a vs-theme and textmate grammar. I used the yeoman-generator to bootstrap an extension and registered all the neccesary files:


var manifest = {
    name: "patcommands",
    displayName: "%displayName%",
    description: "%description%",
    version: "1.0.0",
    publisher: "vscode",
    license: "MIT",
    engines: { vscode: "*" },
    categories: ["Programming Languages", "Themes"],
    contributes: {
        languages: [{ id: "PatCommands", extensions: [".patc"], configuration: "./language-configuration.json" }],
        grammars: [
            { language: "PatCommands", scopeName: "source.Patcommands", path: "./syntaxes/PatCommands.tmLanguage.json" }
        ],
        themes: [
            {
                id: "PatThemeLight",
                "label": "PatThemeLight",
                "uiTheme": "vs",
                "path": "./themes/PatThemeLight.json"
              }
        ]
    }
}

const { registerFileUrl, whenReady } = registerExtension(manifest, undefined, {system: true,})
registerFileUrl(
    "./syntaxes/PatCommands.tmLanguage.json",
    new URL("./syntaxes/PatCommands.tmLanguage.json", import.meta.url).toString(),
    { mimeType: "application/json" }
)
registerFileUrl("./language-configuration.json", new URL("./language-configuration.json", import.meta.url).toString(), {
    mimeType: "application/json"
})
registerFileUrl("themes/PatThemeLight.json", new URL("./themes/PatThemeLight.json", import.meta.url).toString(), { mimeType: "application/json" })
registerFileUrl("package.json", new URL("./package.json", import.meta.url).toString(), { mimeType: "application/json" })

export { whenReady }

and imported the scriptfile into my startup.js. however, setting the my theme to "PatThemeLight" from within the model doesnt seem to use my theme, despite the grammar working fine.

im using

const reader = new BrowserMessageReader(worker)
    const writer = new BrowserMessageWriter(worker)
    await initServices({
        serviceConfig: {
            userServices: {
                ...GetExtensionServiceOverride(),
                ...GetLanguageServiceOverride(),
                ...GetThemeserviceOverride()
            }
        }
    })

as overrides. am i missing something? Thanks in advance for your help and time, it is greatly apprechiated.

CGNonofr commented 2 weeks ago

What do you mean by

setting the my theme to "PatThemeLight" from within the model

?

mep-bsw commented 2 weeks ago

im doing

return monaco.editor.create(element, {
            model: monaco.editor.createModel(initialValue, "PatCommands", Uri.parse("/workspace/test")),
        language: "PatCommands",
        theme: "PatThemeLight",
        value: initialValue,
        readOnly: readonly,
        automaticLayout: true,
        "semanticHighlighting.enabled": true,
        minimap: {
            enabled: false
        }})

to instruct the monaco-instance to use my theme, but it doesnt seem to change anything.

CGNonofr commented 2 weeks ago

Isn't there any error in the console? Can you provide a simple reproduction repo?

Btw the theme is not specific to an editor but global. There is a glue in monaco-editor so that when an editor is created, the provided theme is updated globally but I would recommend setting the theme in the user configuration directly, either by using the configurationDefaults in the IWorkbenchConstructionOptions (3rd parameter of the initialize method) or initializing the user configuration with initUserConfiguration. It allows to configure the theme BEFORE the services are initialized, allowing the storage service to kick in and prevent a flicker during the loading

mep-bsw commented 2 weeks ago

my startup.ts does look like this now:

import { Uri } from 'monaco-editor';

import "../../extensions/patcommands/PatCommands"
import GetThemeserviceOverride from "@codingame/monaco-vscode-theme-service-override";
import GetLanguageServiceOverride from "@codingame/monaco-vscode-languages-service-override";
import GetExtensionServiceOverride from "@codingame/monaco-vscode-extensions-service-override";
import "@codingame/monaco-vscode-theme-defaults-default-extension"

import { BrowserMessageReader, BrowserMessageWriter } from "vscode-languageserver-protocol/browser.js"

import { initServices } from 'monaco-languageclient/vscode/services';
import * as monLanCli from "monaco-languageclient";
import * as monaco from 'monaco-editor';
import { CloseAction, ErrorAction } from 'vscode-languageclient/lib/common/client';
import { worker } from '../components/mixedEnvirons/dev/ConnectionWrapper';

export async function startup(element: HTMLDivElement, initialValue: string, readonly: boolean){
    const reader = new BrowserMessageReader(worker)
    const writer = new BrowserMessageWriter(worker)
    await initServices({
        serviceConfig: {
            userServices: {
                ...GetThemeserviceOverride(),
                ...GetExtensionServiceOverride(),
                ...GetLanguageServiceOverride(),
            }
        }
    })

    const config: monLanCli.MonacoLanguageClientOptions = {
        name: "Patcommands Language Client  ",
        clientOptions: {
            documentSelector: [{ language: "PatCommands" }],
            errorHandler: {
                error: () => ({ action: ErrorAction.Continue }),
                closed: () => ({ action: CloseAction.DoNotRestart })
            }
        },

        connectionProvider: {
            get: () => {
                return Promise.resolve({reader, writer})
            }
        }
    }
    const languageClient = new monLanCli.MonacoLanguageClient(config)
    languageClient.start()
    reader.onClose(() => languageClient.stop())

        return monaco.editor.create(element, {
            model: monaco.editor.createModel(initialValue, "PatCommands", Uri.parse("/workspace/test")),
        language: "PatCommands",
        value: initialValue,
        theme: "Default Dark+",
        readOnly: readonly,
        automaticLayout: true,
        "semanticHighlighting.enabled": true,
        minimap: {
            enabled: false
        },

    })

}

it seems like i can not even load the default themes, so there must be something wrong with the way i do things. and no, i dont get any errors in the console.

CGNonofr commented 2 weeks ago

Can you please provide a fully functional reproduction example so I can easily have a look?

mep-bsw commented 2 weeks ago

it seems like the services didnt finish initializing, i fixed it by adding a delay before initializing the the monaco-instance.:

   await initServices({
        serviceConfig: {
            workspaceConfig: {
                configurationDefaults: {
                    theme: "Default Dark+"
                }
            },
            userServices: {
                ...GetThemeserviceOverride(),
                ...GetExtensionServiceOverride(),
                ...GetLanguageServiceOverride()
            }
        }
    })
    await new Promise<void>((resolve) => {
        setTimeout(() => {
            resolve()
        }, 500);
    })
mep-bsw commented 2 weeks ago

note to self and other people who run into this problem: the promise returned from the whenready-function exported from extensions/ returned by registerextension is actually supposed to be awaited before firing up an monaco-instance...