refine output modifications of NotebookCellExecution

This commit is contained in:
Johannes Rieken
2021-05-28 11:15:56 +02:00
parent 872fac207e
commit 04e09dacdf
3 changed files with 92 additions and 36 deletions
+46 -10
View File
@@ -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<void>;
appendOutput(out: NotebookCellOutput | NotebookCellOutput[], cellIndex?: number): Thenable<void>;
replaceOutput(out: NotebookCellOutput | NotebookCellOutput[], cellIndex?: number): Thenable<void>;
// todo@API use object instead of index?
appendOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], outputId: string): Thenable<void>;
replaceOutputItems(items: NotebookCellOutputItem | NotebookCellOutputItem[], outputId: string): Thenable<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
}
export interface NotebookController {
@@ -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<void> {
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<void> {
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(<vscode.NotebookCellExecution>{
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<void> {
clearOutput(cell?: vscode.NotebookCell | number): Thenable<void> {
that.verifyStateForOutput();
return this.replaceOutput([], cellIndex);
return that.updateOutputs([], cell, false);
},
async appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cellIndex?: number): Promise<void> {
async appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
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<void> {
async replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
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<void> {
async appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
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<void> {
async replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
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);
}
}
+11 -1
View File
@@ -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 (<NotebookCellOutput>candidate).id === 'string' && isArray((<NotebookCellOutput>candidate).outputs);
}
static ensureUniqueMimeTypes(items: NotebookCellOutputItem[], warn: boolean = false): NotebookCellOutputItem[] {
const seen = new Set<string>();
const removeIdx = new Set<number>();