diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 119accc7..94f8cbca 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -122,6 +122,8 @@ import { ExamplesServicePath, ExamplesService } from '../common/protocol/example import { BuiltInExamples, LibraryExamples } from './contributions/examples'; import { LibraryServiceProvider } from './library/library-service-provider'; import { IncludeLibrary } from './contributions/include-library'; +import { OutputChannelManager as TheiaOutputChannelManager } from '@theia/output/lib/common/output-channel'; +import { OutputChannelManager } from './theia/output/output-channel'; const ElementQueries = require('css-element-queries/src/ElementQueries'); @@ -310,6 +312,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { }); bind(OutputWidget).toSelf().inSingletonScope(); rebind(TheiaOutputWidget).toService(OutputWidget); + bind(OutputChannelManager).toSelf().inSingletonScope(); + rebind(TheiaOutputChannelManager).toService(OutputChannelManager); // Show a disconnected status bar, when the daemon is not available bind(ApplicationConnectionStatusContribution).toSelf().inSingletonScope(); diff --git a/arduino-ide-extension/src/browser/theia/output/output-channel.ts b/arduino-ide-extension/src/browser/theia/output/output-channel.ts new file mode 100644 index 00000000..cbd33324 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/output/output-channel.ts @@ -0,0 +1,53 @@ +import * as PQueue from 'p-queue'; +import { injectable } from 'inversify'; +import { Deferred } from '@theia/core/lib/common/promise-util'; +import { OutputUri } from '@theia/output/lib/common/output-uri'; +import { IReference } from '@theia/monaco/lib/browser/monaco-text-model-service'; +import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model'; +import { OutputChannelManager as TheiaOutputChannelManager, OutputChannel as TheiaOutputChannel } from '@theia/output/lib/common/output-channel'; + +@injectable() +export class OutputChannelManager extends TheiaOutputChannelManager { + + getChannel(name: string): TheiaOutputChannel { + const existing = this.channels.get(name); + if (existing) { + return existing; + } + + // We have to register the resource first, because `textModelService#createModelReference` will require it + // right after creating the monaco.editor.ITextModel. + // All `append` and `appendLine` will be deferred until the underlying text-model instantiation. + let resource = this.resources.get(name); + if (!resource) { + const uri = OutputUri.create(name); + const editorModelRef = new Deferred>(); + resource = this.createResource({ uri, editorModelRef }); + this.resources.set(name, resource); + this.textModelService.createModelReference(uri).then(ref => editorModelRef.resolve(ref)); + } + + const channel = new OutputChannel(resource, this.preferences); + this.channels.set(name, channel); + this.toDisposeOnChannelDeletion.set(name, this.registerListeners(channel)); + this.channelAddedEmitter.fire(channel); + if (!this.selectedChannel) { + this.selectedChannel = channel; + } + return channel; + } + +} + +export class OutputChannel extends TheiaOutputChannel { + + dispose(): void { + super.dispose(); + if ((this as any).disposed) { + const textModifyQueue: PQueue = (this as any).textModifyQueue; + textModifyQueue.pause(); + textModifyQueue.clear(); + } + } + +}