diff --git a/packages/extension/src/browser/vscode/api/main.thread.output.ts b/packages/extension/src/browser/vscode/api/main.thread.output.ts index 05f7ceafe8..da32461fd5 100644 --- a/packages/extension/src/browser/vscode/api/main.thread.output.ts +++ b/packages/extension/src/browser/vscode/api/main.thread.output.ts @@ -40,6 +40,14 @@ export class MainThreadOutput implements IMainThreadOutput { return Promise.resolve(); } + $appendLine(channelName: string, value: string): PromiseLike { + const outputChannel = this.getChannel(channelName); + if (outputChannel) { + outputChannel.appendLine(value); + } + return Promise.resolve(); + } + $clear(channelName: string): PromiseLike { const outputChannel = this.getChannel(channelName); if (outputChannel) { diff --git a/packages/extension/src/common/vscode/window.ts b/packages/extension/src/common/vscode/window.ts index e36c831e61..6ffbce021f 100644 --- a/packages/extension/src/common/vscode/window.ts +++ b/packages/extension/src/common/vscode/window.ts @@ -182,6 +182,7 @@ export interface IExtHostStatusBar { export interface IMainThreadOutput { $append(channelName: string, value: string): PromiseLike; + $appendLine(channelName: string, value: string): PromiseLike; $replace(channelName: string, value: string): PromiseLike; $clear(channelName: string): PromiseLike; $dispose(channelName: string): PromiseLike; diff --git a/packages/extension/src/hosted/api/vscode/ext.host.output.ts b/packages/extension/src/hosted/api/vscode/ext.host.output.ts index 3038094751..30016ed1af 100644 --- a/packages/extension/src/hosted/api/vscode/ext.host.output.ts +++ b/packages/extension/src/hosted/api/vscode/ext.host.output.ts @@ -95,7 +95,7 @@ export class OutputChannelImpl implements types.OutputChannel { appendLine(value: string): void { this.validate(); - this.append(value + '\n'); + this.#proxy.$appendLine(this.name, value); } clear(): void { @@ -161,22 +161,15 @@ export class LogOutputChannelImpl extends OutputChannelImpl implements types.Log } private now(): string { + const twoDigits = (v: number) => (v < 10 ? `0${v}` : v); + const threeDigits = (v: number) => (v < 10 ? `00${v}` : v < 100 ? `0${v}` : v); + const now = new Date(); - return ( - padLeft(now.getFullYear() + '', 4, '0') + - '-' + - padLeft(now.getMonth() + 1 + '', 2, '0') + - '-' + - padLeft(now.getDate() + '', 2, '0') + - ' ' + - padLeft(now.getUTCHours() + '', 2, '0') + - ':' + - padLeft(now.getMinutes() + '', 2, '0') + - ':' + - padLeft(now.getUTCSeconds() + '', 2, '0') + - '.' + - now.getMilliseconds() - ); + const date = `${now.getFullYear()}-${twoDigits(now.getMonth() + 1)}-${twoDigits(now.getDate())}`; + const time = `${twoDigits(now.getHours())}:${twoDigits(now.getMinutes())}:${twoDigits( + now.getSeconds(), + )}.${threeDigits(now.getMilliseconds())}`; + return `${date} ${time}`; } private label(level: types.OutputChannelLogLevel) { @@ -197,7 +190,7 @@ export class LogOutputChannelImpl extends OutputChannelImpl implements types.Log } private logWithLevel(level: types.OutputChannelLogLevel, message: string, data?: any): void { - this.append(`${this.now()} [${this.label(level)}] ${message}`); + this.appendLine(`${this.now()} [${this.label(level)}] ${message}`); if (data) { this.append(this.data2String(data)); } @@ -223,7 +216,3 @@ export class LogOutputChannelImpl extends OutputChannelImpl implements types.Log this.logWithLevel(types.OutputChannelLogLevel.Error, error.toString(), args); } } - -function padLeft(s: string, n: number, pad = ' ') { - return pad.repeat(Math.max(0, n - s.length)) + s; -} diff --git a/packages/output/src/browser/output.channel.ts b/packages/output/src/browser/output.channel.ts index 243644fcc4..e1ab842ad3 100644 --- a/packages/output/src/browser/output.channel.ts +++ b/packages/output/src/browser/output.channel.ts @@ -6,6 +6,7 @@ import { IEditorDocumentModelRef, IEditorDocumentModelService } from '@opensumi/ import { IMainLayoutService } from '@opensumi/ide-main-layout'; import * as monaco from '@opensumi/ide-monaco'; import { ITextModel } from '@opensumi/ide-monaco/lib/browser/monaco-api/types'; +import { EditOperation } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/editOperation'; import { ContentChangeEvent, ContentChangeEventPayload, ContentChangeType } from '../common'; @@ -117,21 +118,11 @@ export class OutputChannel extends Disposable { this.monacoModel.setValue(value); } - private pushEditOperations(value: string): void { - const lineCount = this.monacoModel.getLineCount(); - const character = value.length; - // 用 pushEditOperations 插入文本,直接替换 content 会触发重新计算高亮 - this.monacoModel.pushEditOperations( - [], - [ - { - range: new monaco.Range(lineCount, 0, lineCount + 1, character), - text: value, - forceMoveMarkers: true, - }, - ], - () => [], - ); + private applyEdits(value: string): void { + const lastLine = this.monacoModel.getLineCount(); + const lastLineMaxColumn = this.monacoModel.getLineMaxColumn(lastLine); + const edits = [EditOperation.insert(new monaco.Position(lastLine, lastLineMaxColumn), value)]; + this.monacoModel.applyEdits(edits); } private isEmptyChannel(): boolean { @@ -149,7 +140,7 @@ export class OutputChannel extends Disposable { if (this.isEmptyChannel() || needSlice) { this.doReplace(this.outputLines.join('') + value); } else { - this.pushEditOperations(value); + this.applyEdits(value); } this.outputLines.push(value); });