{"version":3,"sources":["browser/textmate/monaco-textmate-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;kFAckF;AAGlF,OAAO,EAAC,QAAQ,EAAgC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAC,oBAAoB,EAAE,UAAU,EAAE,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAC/F,OAAO,EAAC,+BAA+B,EAAC,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAC,YAAY,EAAC,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAuB,qCAAqC,EAAC,MAAM,yBAAyB,CAAC;AACpG,OAAO,EAA0B,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAC,mBAAmB,EAAC,MAAM,yBAAyB,CAAC;AAE5D,eAAO,MAAM,cAAc,eAA2B,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE/C,qBACa,qBAAsB,YAAW,+BAA+B;IAEzE,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAEjD;IAEF,SAAS,CAAC,QAAQ,CAAC,mBAAmB,cAAqB;IAE3D,SAAS,CAAC,eAAe,EAAE,QAAQ,CAAC;IAGpC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;IAGjG,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAGtD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IAG9C,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAC5D,SAAS,CAAC,QAAQ,CAAC,sBAAsB,uBAA8B;IAEvE,SAAS,KAAK,kBAAkB,IAAI,MAAM,CAEzC;IAED,UAAU,IAAI,IAAI;IAuDlB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAW9C,SAAS,CAAC,WAAW,IAAI,IAAI;cAkBb,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4CtG,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,UAAU;CAYxE","file":"../../../src/browser/textmate/monaco-textmate-service.d.ts","sourcesContent":["/********************************************************************************\r\n * Copyright (C) 2018 Redhat, Ericsson and others.\r\n *\r\n * This program and the accompanying materials are made available under the\r\n * terms of the Eclipse Public License v. 2.0 which is available at\r\n * http://www.eclipse.org/legal/epl-2.0.\r\n *\r\n * This Source Code may also be made available under the following Secondary\r\n * Licenses when the conditions for such availability set forth in the Eclipse\r\n * Public License v. 2.0 are satisfied: GNU General Public License, version 2\r\n * with the GNU Classpath Exception which is available at\r\n * https://www.gnu.org/software/classpath/license.html.\r\n *\r\n * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0\r\n ********************************************************************************/\r\n\r\nimport {inject, injectable, named} from 'inversify';\r\nimport {IOnigLib, IRawGrammar, parseRawGrammar, Registry} from 'vscode-textmate';\r\nimport {ContributionProvider, Disposable, DisposableCollection} from '@tartjs/core/lib/common';\r\nimport {FrontendApplicationContribution} from '@tartjs/core/lib/browser';\r\nimport {ThemeService} from '@tartjs/core/lib/browser/theming';\r\nimport {getEncodedLanguageId, LanguageGrammarDefinitionContribution} from './textmate-contribution';\r\nimport {createTextmateTokenizer, TokenizerOption} from './textmate-tokenizer';\r\nimport {TextmateRegistry} from './textmate-registry';\r\nimport {MonacoThemeRegistry} from './monaco-theme-registry';\r\n\r\nexport const OnigasmPromise = Symbol('OnigasmPromise');\r\nexport type OnigasmPromise = Promise<IOnigLib>;\r\n\r\n@injectable()\r\nexport class MonacoTextmateService implements FrontendApplicationContribution {\r\n\r\n    protected readonly tokenizerOption: TokenizerOption = {\r\n        lineLimit: 400\r\n    };\r\n\r\n    protected readonly _activatedLanguages = new Set<string>();\r\n\r\n    protected grammarRegistry: Registry;\r\n\r\n    @inject(ContributionProvider) @named(LanguageGrammarDefinitionContribution)\r\n    protected readonly grammarProviders: ContributionProvider<LanguageGrammarDefinitionContribution>;\r\n\r\n    @inject(TextmateRegistry)\r\n    protected readonly textmateRegistry: TextmateRegistry;\r\n\r\n    @inject(OnigasmPromise)\r\n    protected readonly onigasmPromise: OnigasmPromise;\r\n\r\n    @inject(ThemeService)\r\n    protected readonly themeService: ThemeService;\r\n\r\n    @inject(MonacoThemeRegistry)\r\n    protected readonly monacoThemeRegistry: MonacoThemeRegistry;\r\n    protected readonly toDisposeOnUpdateTheme = new DisposableCollection();\r\n\r\n    protected get currentEditorTheme(): string {\r\n        return this.themeService.getCurrentTheme().editorTheme || 'dark-wm';\r\n    }\r\n\r\n    initialize(): void {\r\n        // if (!isBasicWasmSupported) {\r\n        //     console.log('Textmate support deactivated because WebAssembly is not detected.');\r\n        //     return;\r\n        // }\r\n\r\n        for (const grammarProvider of this.grammarProviders.getContributions()) {\r\n            try {\r\n                grammarProvider.registerTextmateLanguage(this.textmateRegistry);\r\n            } catch (err) {\r\n                console.error(err);\r\n            }\r\n        }\r\n\r\n        this.grammarRegistry = new Registry({\r\n            getOnigLib: () => this.onigasmPromise,\r\n            theme: this.monacoThemeRegistry.getThemeData(this.currentEditorTheme),\r\n            loadGrammar: async (scopeName: string) => {\r\n                const provider = this.textmateRegistry.getProvider(scopeName);\r\n                if (provider) {\r\n                    const definition = await provider.getGrammarDefinition();\r\n                    let rawGrammar: IRawGrammar;\r\n                    if (typeof definition.content === 'string') {\r\n                        rawGrammar = parseRawGrammar(definition.content, definition.format === 'json' ? 'grammar.json' : 'grammar.plist');\r\n                    } else {\r\n                        rawGrammar = definition.content as IRawGrammar;\r\n                    }\r\n                    return rawGrammar;\r\n                }\r\n                return undefined;\r\n            },\r\n            getInjections: (scopeName: string) => {\r\n                const provider = this.textmateRegistry.getProvider(scopeName);\r\n                if (provider && provider.getInjections) {\r\n                    return provider.getInjections(scopeName);\r\n                }\r\n                return [];\r\n            }\r\n        });\r\n\r\n        // this.tokenizerOption.lineLimit = this.preferences['editor.maxTokenizationLineLength'];\r\n        // this.preferences.onPreferenceChanged(e => {\r\n        //     if (e.preferenceName === 'editor.maxTokenizationLineLength') {\r\n        //         this.tokenizerOption.lineLimit = e.newValue;\r\n        //     }\r\n        // });\r\n\r\n        this.updateTheme();\r\n        this.themeService.onDidColorThemeChange(() => this.updateTheme());\r\n\r\n        for (const id of this.textmateRegistry.languages) {\r\n            this.activateLanguage(id);\r\n        }\r\n    }\r\n\r\n    activateLanguage(language: string): Disposable {\r\n        const toDispose = new DisposableCollection(\r\n            Disposable.create(() => { /* mark as not disposed */\r\n            })\r\n        );\r\n        toDispose.push(this.waitForLanguage(language, () =>\r\n            this.doActivateLanguage(language, toDispose)\r\n        ));\r\n        return toDispose;\r\n    }\r\n\r\n    protected updateTheme(): void {\r\n        this.toDisposeOnUpdateTheme.dispose();\r\n\r\n        const currentEditorTheme = this.currentEditorTheme;\r\n        document.body.classList.add(currentEditorTheme);\r\n        this.toDisposeOnUpdateTheme.push(Disposable.create(() => document.body.classList.remove(currentEditorTheme)));\r\n\r\n        // first update registry to run tokenization with the proper theme\r\n        const theme = this.monacoThemeRegistry.getThemeData(currentEditorTheme);\r\n        if (theme) {\r\n            this.grammarRegistry.setTheme(theme);\r\n        }\r\n\r\n        // then trigger tokenization by setting monaco theme\r\n        monaco.editor.setTheme(currentEditorTheme);\r\n        monaco.services.StaticServices.standaloneThemeService.get().setTheme(currentEditorTheme);\r\n    }\r\n\r\n    protected async doActivateLanguage(languageId: string, toDispose: DisposableCollection): Promise<void> {\r\n        if (this._activatedLanguages.has(languageId)) {\r\n            return;\r\n        }\r\n        this._activatedLanguages.add(languageId);\r\n        toDispose.push(Disposable.create(() => this._activatedLanguages.delete(languageId)));\r\n\r\n        const scopeName = this.textmateRegistry.getScope(languageId);\r\n        if (!scopeName) {\r\n            return;\r\n        }\r\n        const provider = this.textmateRegistry.getProvider(scopeName);\r\n        if (!provider) {\r\n            return;\r\n        }\r\n\r\n        const configuration = this.textmateRegistry.getGrammarConfiguration(languageId);\r\n        const initialLanguage = getEncodedLanguageId(languageId);\r\n\r\n        await this.onigasmPromise;\r\n        if (toDispose.disposed) {\r\n            return;\r\n        }\r\n        try {\r\n            const grammar = await this.grammarRegistry.loadGrammarWithConfiguration(scopeName, initialLanguage, configuration);\r\n            if (toDispose.disposed) {\r\n                return;\r\n            }\r\n            if (!grammar) {\r\n                throw new Error(`no grammar for ${scopeName}, ${initialLanguage}, ${JSON.stringify(configuration)}`);\r\n            }\r\n            const options = configuration.tokenizerOption ? configuration.tokenizerOption : this.tokenizerOption;\r\n            const tokenizer = createTextmateTokenizer(grammar, options);\r\n            toDispose.push(monaco.languages.setTokensProvider(languageId, tokenizer));\r\n            const support = monaco.modes.TokenizationRegistry.get(languageId);\r\n            const themeService = monaco.services.StaticServices.standaloneThemeService.get();\r\n            const languageIdentifier = monaco.services.StaticServices.modeService.get().getLanguageIdentifier(languageId);\r\n            const adapter = new monaco.services.TokenizationSupport2Adapter(themeService, languageIdentifier!, tokenizer);\r\n            support!.tokenize = adapter.tokenize.bind(adapter);\r\n        } catch (error) {\r\n            console.warn('No grammar for this language id', languageId, error);\r\n        }\r\n    }\r\n\r\n    protected waitForLanguage(language: string, cb: () => {}): Disposable {\r\n        const modeService = monaco.services.StaticServices.modeService.get();\r\n        for (const modeId of Object.keys(modeService['_instantiatedModes'])) {\r\n            const mode = modeService['_instantiatedModes'][modeId];\r\n            if (mode.getId() === language) {\r\n                cb();\r\n                return Disposable.NULL;\r\n            }\r\n        }\r\n        return monaco.languages.onLanguage(language, cb);\r\n    }\r\n\r\n}\r\n"]}