diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index c1efc9b757e..07f0bed6bc5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1601,9 +1601,6 @@ declare module 'vscode' { */ readonly token: CancellationToken; - //todo@API remove? use cell.notebook instead? - readonly document: NotebookDocument; - /** * Set and unset the order of this cell execution. */ @@ -1614,13 +1611,52 @@ declare module 'vscode' { // todo@API inline context object? end(result?: NotebookCellExecuteEndContext): void; - // todo@API use object instead of index? FF - clearOutput(cellIndex?: number): Thenable; - appendOutput(out: NotebookCellOutput | NotebookCellOutput[], cellIndex?: number): Thenable; - replaceOutput(out: NotebookCellOutput | NotebookCellOutput[], cellIndex?: number): Thenable; - // todo@API use object instead of index? - appendOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], outputId: string): Thenable; - replaceOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], outputId: string): Thenable; + /** + * Clears the output of the cell that is executing or of another cell that is affected by this execution. + * + * @param cell Cell for which output is cleared. Defaults to the {@link NotebookCellExecution.cell cell} of + * this execution. + * @return A thenable that resolves when the operation finished. + */ + clearOutput(cell?: NotebookCell): Thenable; + + /** + * Replace the output of the cell that is executing or of another cell that is affected by this execution. + * + * @param out Output that replaces the current output. + * @param cell Cell for which output is cleared. Defaults to the {@link NotebookCellExecution.cell cell} of + * this execution. + * @return A thenable that resolves when the operation finished. + */ + replaceOutput(out: NotebookCellOutput | NotebookCellOutput[], cell?: NotebookCell): Thenable; + + /** + * Append to the output of the cell that is executing or to another cell that is affected by this execution. + * + * @param out Output that is appended to the current output. + * @param cell Cell for which output is cleared. Defaults to the {@link NotebookCellExecution.cell cell} of + * this execution. + * @return A thenable that resolves when the operation finished. + */ + appendOutput(out: NotebookCellOutput | NotebookCellOutput[], cell?: NotebookCell): Thenable; + + /** + * Replace all output items of existing cell output. + * + * @param items Output items that replace the items of existing output. + * @param output Output object or the identifier of one. + * @return A thenable that resolves when the operation finished. + */ + replaceOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], output: NotebookCellOutput | string): Thenable; + + /** + * Append output items to existing cell output. + * + * @param items Output items that are append to existing output. + * @param output Output object or the identifier of one. + * @return A thenable that resolves when the operation finished. + */ + appendOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], output: NotebookCellOutput | string): Thenable; } export interface NotebookController { diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 9cf31f438e7..8644c2a336a 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -381,13 +381,16 @@ class NotebookCellExecutionTask extends Disposable { this.applyEdits([edit]); } - private cellIndexToHandle(cellIndex: number | undefined): number { - if (typeof cellIndex !== 'number') { - return this._cell.handle; + private cellIndexToHandle(cellOrCellIndex: vscode.NotebookCell | number | undefined): number { + let cell: ExtHostCell | undefined = this._cell; + if (typeof cellOrCellIndex === 'number') { + // todo@jrieken remove support for number shortly + cell = this._document.getCellFromIndex(cellOrCellIndex); + } else if (cellOrCellIndex) { + cell = this._document.getCellFromApiCell(cellOrCellIndex); } - const cell = this._document.getCellFromIndex(cellIndex); if (!cell) { - throw new Error('INVALID cell index'); + throw new Error('INVALID cell'); } return cell.handle; } @@ -406,13 +409,25 @@ class NotebookCellExecutionTask extends Disposable { }); } + private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | number | undefined, append: boolean): Promise { + const handle = this.cellIndexToHandle(cell); + const outputDtos = this.validateAndConvertOutputs(asArray(outputs)); + return this.applyEditSoon({ editType: CellEditType.Output, handle, append, outputs: outputDtos }); + } + + private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputOrOutputId: vscode.NotebookCellOutput | string, append: boolean): Promise { + if (NotebookCellOutput.isNotebookCellOutput(outputOrOutputId)) { + outputOrOutputId = outputOrOutputId.id; + } + items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true); + return this.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId: outputOrOutputId, append }); + } + asApiObject(): vscode.NotebookCellExecution { const that = this; - return Object.freeze({ + const result: vscode.NotebookCellExecution = { get token() { return that._tokenSource.token; }, - get document() { return that._document.apiNotebook; }, get cell() { return that._cell.apiCell; }, - get executionOrder() { return that._executionOrder; }, set executionOrder(v: number | undefined) { that._executionOrder = v; @@ -450,37 +465,32 @@ class NotebookCellExecutionTask extends Disposable { }); }, - clearOutput(cellIndex?: number): Thenable { + clearOutput(cell?: vscode.NotebookCell | number): Thenable { that.verifyStateForOutput(); - return this.replaceOutput([], cellIndex); + return that.updateOutputs([], cell, false); }, - async appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cellIndex?: number): Promise { + async appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise { that.verifyStateForOutput(); - const handle = that.cellIndexToHandle(cellIndex); - const outputDtos = that.validateAndConvertOutputs(asArray(outputs)); - return that.applyEditSoon({ editType: CellEditType.Output, handle, append: true, outputs: outputDtos }); + return that.updateOutputs(outputs, cell, true); }, - async replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cellIndex?: number): Promise { + async replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise { that.verifyStateForOutput(); - const handle = that.cellIndexToHandle(cellIndex); - const outputDtos = that.validateAndConvertOutputs(asArray(outputs)); - return that.applyEditSoon({ editType: CellEditType.Output, handle, outputs: outputDtos }); + return that.updateOutputs(outputs, cell, false); }, - async appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputId: string): Promise { + async appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise { that.verifyStateForOutput(); - items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true); - return that.applyEditSoon({ editType: CellEditType.OutputItems, append: true, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId }); + that.updateOutputItems(items, output, true); }, - async replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputId: string): Promise { + async replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise { that.verifyStateForOutput(); - items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true); - return that.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId }); + that.updateOutputItems(items, output, false); } - }); + }; + return Object.freeze(result); } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index ece6bab4537..cd6359ba7c8 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -9,7 +9,7 @@ import { IRelativePattern } from 'vs/base/common/glob'; import { isMarkdownString, MarkdownString as BaseMarkdownString } from 'vs/base/common/htmlContent'; import { ReadonlyMapView, ResourceMap } from 'vs/base/common/map'; import { normalizeMimeType } from 'vs/base/common/mime'; -import { isStringArray } from 'vs/base/common/types'; +import { isArray, isStringArray } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files'; @@ -3164,6 +3164,16 @@ export class NotebookCellOutputItem { export class NotebookCellOutput { + static isNotebookCellOutput(candidate: any): candidate is NotebookCellOutput { + if (candidate instanceof NotebookCellOutput) { + return true; + } + if (!candidate || typeof candidate !== 'object') { + return false; + } + return typeof (candidate).id === 'string' && isArray((candidate).outputs); + } + static ensureUniqueMimeTypes(items: NotebookCellOutputItem[], warn: boolean = false): NotebookCellOutputItem[] { const seen = new Set(); const removeIdx = new Set();