Skip to content

Commit

Permalink
fix: update service initialization/usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Loïc Mangeonjean committed Oct 16, 2023
1 parent 45d9370 commit 4b2ddda
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 67 deletions.
8 changes: 3 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as monaco from 'monaco-editor'
import { createEditor, registerEditorOpenHandler, registerTextModelContentProvider } from './monaco'
import { defineVSCodeTheme } from './theme'
import { createEditor, createModelReference, registerEditorOpenHandler, initializePromise } from './monaco'
import { updateUserConfiguration, registerConfigurations, registerDefaultConfigurations, onConfigurationChanged, getConfiguration, getUserConfiguration, onUserConfigurationChange } from './configuration'
import { getMonacoLanguage, loadLanguage } from './languages'
import { updateKeybindings, updateEditorKeybindingsMode } from './keybindings'
Expand All @@ -9,9 +8,9 @@ export * from './tools'

export {
monaco,
initializePromise,
createEditor,

defineVSCodeTheme,
createModelReference,

registerConfigurations,
registerDefaultConfigurations,
Expand All @@ -24,7 +23,6 @@ export {
updateKeybindings,

getMonacoLanguage,
registerTextModelContentProvider,
registerEditorOpenHandler,
loadLanguage
}
62 changes: 15 additions & 47 deletions src/monaco.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,42 @@
import * as monaco from 'monaco-editor'
import { IReference, ITextFileEditorModel, createConfiguredEditor, errorHandler, createModelReference as vscodeCreateModelReference } from 'vscode/monaco'
import { initialize, editorOpenHandlerRegistry } from './services'
import './extensions'
import './languages'
import './theme'
import { StandaloneServices, ITextModelService, ITextModelContentProvider } from 'vscode/services'
import getModelEditorServiceOverride from 'vscode/service-override/modelEditor'
import getDialogServiceOverride from 'vscode/service-override/dialogs'
import getConfigurationServiceOverride from 'vscode/service-override/configuration'
import getKeybindingsServiceOverride from 'vscode/service-override/keybindings'
import getTextmateServiceOverride from 'vscode/service-override/textmate'
import getThemeServiceOverride from 'vscode/service-override/theme'
import geTokenClassificationServiceOverride from 'vscode/service-override/tokenClassification'
import getLanguageConfigurationServiceOverride from 'vscode/service-override/languageConfiguration'
import getSnippetConfigurationServiceOverride from 'vscode/service-override/snippets'
import getLanguagesServiceOverride from 'vscode/service-override/languages'
import './worker'
import { createConfiguredEditor, errorHandler } from 'vscode/monaco'
import onigFile from 'vscode-oniguruma/release/onig.wasm'
import setupExtensions from './extensions'
import 'monaco-editor/esm/vs/editor/editor.all'
import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp'
import setupExtensions from './editor'
import 'monaco-editor'
import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard'
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess'
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess'
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess'
import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess'
import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch'
import EditorOpenHandlerRegistry, { EditorOpenHandler } from './tools/EditorOpenHandlerRegistry'

const editorOpenHandlerRegistry = new EditorOpenHandlerRegistry()

StandaloneServices.initialize({
...getModelEditorServiceOverride((model, input, sideBySide) => {
return editorOpenHandlerRegistry.openCodeEditor(model, input, sideBySide)
}),
...getDialogServiceOverride(),
...getConfigurationServiceOverride(),
...getKeybindingsServiceOverride(),
...getTextmateServiceOverride(async () => {
const response = await fetch(onigFile)
return await response.arrayBuffer()
}),
...getThemeServiceOverride(),
...geTokenClassificationServiceOverride(),
...getLanguageConfigurationServiceOverride(),
...getSnippetConfigurationServiceOverride(),
...getLanguagesServiceOverride()
})
import { EditorOpenHandler } from './tools/EditorOpenHandlerRegistry'

errorHandler.setUnexpectedErrorHandler(error => {
console.warn('Unexpected error', error)
})

function createEditor (domElement: HTMLElement, options?: monaco.editor.IStandaloneEditorConstructionOptions): monaco.editor.IStandaloneCodeEditor {
const initializePromise = initialize()

async function createEditor (domElement: HTMLElement, options?: monaco.editor.IStandaloneEditorConstructionOptions): Promise<monaco.editor.IStandaloneCodeEditor> {
await initializePromise
const editor = createConfiguredEditor(domElement, options)

setupExtensions(editor)

return editor
}

function registerTextModelContentProvider (scheme: string, provider: ITextModelContentProvider): monaco.IDisposable {
const textModelService = StandaloneServices.get(ITextModelService)
return textModelService.registerTextModelContentProvider(scheme, provider)
async function createModelReference (resource: monaco.Uri, content?: string): Promise<IReference<ITextFileEditorModel>> {
await initializePromise
return vscodeCreateModelReference(resource, content)
}

function registerEditorOpenHandler (handler: EditorOpenHandler): monaco.IDisposable {
return editorOpenHandlerRegistry.registerEditorOpenHandler(handler)
}

export {
initializePromise,
createEditor,
registerTextModelContentProvider,
createModelReference,
registerEditorOpenHandler
}
92 changes: 92 additions & 0 deletions src/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import getExtensionServiceOverride from '@codingame/monaco-vscode-extensions-service-override'
import getModelServiceOverride from '@codingame/monaco-vscode-model-service-override'
import getDialogsServiceOverride from '@codingame/monaco-vscode-dialogs-service-override'
import getConfigurationServiceOverride from '@codingame/monaco-vscode-configuration-service-override'
import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override'
import getTextmateServiceOverride from '@codingame/monaco-vscode-textmate-service-override'
import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override'
import getLanguagesServiceOverride from '@codingame/monaco-vscode-languages-service-override'
import getAudioCueServiceOverride from '@codingame/monaco-vscode-audio-cue-service-override'
import getPreferencesServiceOverride from '@codingame/monaco-vscode-preferences-service-override'
import getSnippetServiceOverride from '@codingame/monaco-vscode-snippets-service-override'
import getAccessibilityServiceOverride from '@codingame/monaco-vscode-accessibility-service-override'
import getLanguageDetectionWorkerServiceOverride from '@codingame/monaco-vscode-language-detection-worker-service-override'
import getEditorServiceOverride from '@codingame/monaco-vscode-editor-service-override'
import getStorageServiceOverride from '@codingame/monaco-vscode-storage-service-override'
import getLifecycleServiceOverride from '@codingame/monaco-vscode-lifecycle-service-override'
import getQuickAccessServiceOverride from '@codingame/monaco-vscode-quickaccess-service-override'
import { ILogService, LogLevel, StandaloneServices, initialize as initializeServices } from 'vscode/services'
import { initialize as initializeExtensions } from 'vscode/extensions'
import * as monaco from 'monaco-editor'
import EditorOpenHandlerRegistry from './tools/EditorOpenHandlerRegistry'

const editorOpenHandlerRegistry = new EditorOpenHandlerRegistry()

function getExtensionWorkerConfig () {
// Hack bundler Worker detection to get the worker url
class Worker {
constructor (public url: string | URL, public options?: WorkerOptions) {
}
}
const fakeWorker = new Worker(new URL('vscode/workers/extensionHost.worker', import.meta.url))
return {
url: fakeWorker.url.toString(),
options: fakeWorker.options
}
}

export function useGlobalPicker (): boolean {
// TODO should picker and keybindings be global or per-editor
return false
}

let services: monaco.editor.IEditorOverrideServices = {
...getExtensionServiceOverride(getExtensionWorkerConfig()),
...getModelServiceOverride(),
...getDialogsServiceOverride(),
...getConfigurationServiceOverride(monaco.Uri.file('/tmp/project')),
...getKeybindingsServiceOverride({
shouldUseGlobalKeybindings () {
return useGlobalPicker()
}
}),
...getTextmateServiceOverride(),
...getThemeServiceOverride(),
...getLanguagesServiceOverride(),
...getAudioCueServiceOverride(),
...getPreferencesServiceOverride(),
...getSnippetServiceOverride(),
...getLanguageDetectionWorkerServiceOverride(),
...getEditorServiceOverride((model, input, sideBySide) => {
return editorOpenHandlerRegistry.openCodeEditor(model, input, sideBySide)
}),
...getAccessibilityServiceOverride(),
...getStorageServiceOverride(),
...getLifecycleServiceOverride(),
...getQuickAccessServiceOverride({
shouldUseGlobalPicker () {
return useGlobalPicker()
}
})
}

export function registerServices (newServices: monaco.editor.IEditorOverrideServices): void {
services = {
...services,
...newServices
}
}

export async function initialize (): Promise<void> {
// wait a short time for the services to be registered
await new Promise(resolve => setTimeout(resolve, 0))

await initializeServices(services)
StandaloneServices.get(ILogService).setLevel(LogLevel.Off)

await initializeExtensions()
}

export {
editorOpenHandlerRegistry
}
30 changes: 15 additions & 15 deletions src/tools/EditorOpenHandlerRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as monaco from 'monaco-editor'
import { OpenEditor, IEditorOptions } from 'vscode/service-override/modelEditor'
import { OpenEditor, IEditorOptions, IResolvedTextEditorModel } from '@codingame/monaco-vscode-editor-service-override'
import { IReference } from 'vscode/monaco'
import { createEditor } from '../monaco'
import { getConfiguration } from '../configuration'

let currentEditor: ({
model: monaco.editor.ITextModel
editor: monaco.editor.IStandaloneCodeEditor
} & monaco.IDisposable) | null = null
function openNewCodeEditor (model: monaco.editor.ITextModel) {
if (currentEditor != null && model === currentEditor.model) {
async function openNewCodeEditor (modelRef: IReference<IResolvedTextEditorModel>) {
if (currentEditor != null && modelRef.object.textEditorModel === currentEditor.model) {
return currentEditor.editor
}
if (currentEditor != null) {
Expand All @@ -33,23 +33,23 @@ function openNewCodeEditor (model: monaco.editor.ITextModel) {

document.body.appendChild(container)
try {
const editor = createEditor(
const editor = await createEditor(
editorElem,
{
model,
model: modelRef.object.textEditorModel,
readOnly: true,
automaticLayout: true,
...getConfiguration(model.getLanguageId(), 'editor')
automaticLayout: true
}
)

currentEditor = {
dispose: () => {
modelRef.dispose()
editor.dispose()
document.body.removeChild(container)
currentEditor = null
},
model,
model: modelRef.object.textEditorModel,
editor
}

Expand All @@ -69,7 +69,7 @@ function openNewCodeEditor (model: monaco.editor.ITextModel) {
}
}

export type EditorOpenHandler = (model: monaco.editor.ITextModel, input: IEditorOptions | undefined, editor: monaco.editor.ICodeEditor | null, sideBySide?: boolean) => Promise<monaco.editor.ICodeEditor | null>
export type EditorOpenHandler = (modelRef: IReference<IResolvedTextEditorModel>, input: IEditorOptions | undefined, editor: monaco.editor.ICodeEditor | null, sideBySide?: boolean) => Promise<monaco.editor.ICodeEditor | null>

export default class EditorOpenHandlerRegistry {
private handlers: EditorOpenHandler[] = []
Expand All @@ -86,27 +86,27 @@ export default class EditorOpenHandlerRegistry {
}
}

openCodeEditor: OpenEditor = async (model, options, sideBySide?) => {
openCodeEditor: OpenEditor = async (modelRef, options, sideBySide?) => {
let modelEditor: monaco.editor.ICodeEditor | undefined
for (const handler of this.handlers) {
const handlerEditor = await handler(model, options, null, sideBySide)
const handlerEditor = await handler(modelRef, options, null, sideBySide)
if (handlerEditor != null) {
modelEditor = handlerEditor
break
}
}
if (modelEditor == null) {
modelEditor = openNewCodeEditor(model)
modelEditor = await openNewCodeEditor(modelRef)

// Destroy model ref when we close the editor popup
const onModelUnmount = () => {
model.dispose()
modelRef.dispose()
}
const onDidDisposeDisposable = modelEditor.onDidDispose(() => {
onModelUnmount()
})
const onDidChangeModelDisposable = modelEditor.onDidChangeModel((e) => {
if (e.newModelUrl == null || e.newModelUrl.toString() !== model.uri.toString()) {
if (e.newModelUrl == null || e.newModelUrl.toString() !== modelRef.object.textEditorModel.uri.toString()) {
onModelUnmount()
onDidDisposeDisposable.dispose()
onDidChangeModelDisposable.dispose()
Expand Down

0 comments on commit 4b2ddda

Please sign in to comment.