From 6c9398c3eafcfb3f3df8d6838fdc099d36b589e8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 23 Apr 2020 17:02:57 -0700 Subject: [PATCH] clear cell output in the core --- .../workbench/api/common/extHostNotebook.ts | 13 ++++ .../notebook/browser/contrib/coreActions.ts | 70 +++++++++++++++++++ .../notebook/browser/notebookEditor.ts | 10 ++- .../common/model/notebookTextModel.ts | 22 ++++++ .../contrib/notebook/common/notebookCommon.ts | 17 ++++- 5 files changed, 129 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 99911194b28..4262005cc3a 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -251,6 +251,10 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo this.$spliceNotebookCells(event.changes); } else if (event.kind === NotebookCellsChangeType.Move) { this.$moveCell(event.index, event.newIdx); + } else if (event.kind === NotebookCellsChangeType.CellClearOutput) { + this.$clearCellOutputs(event.index); + } else if (event.kind === NotebookCellsChangeType.CellsClearOutput) { + this.$clearAllCellOutputs(); } this._versionId = event.versionId; @@ -299,6 +303,15 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo this.cells.splice(newIdx, 0, ...cells); } + private $clearCellOutputs(index: number) { + const cell = this.cells[index]; + cell.outputs = []; + } + + private $clearAllCellOutputs() { + this.cells.forEach(cell => cell.outputs = []); + } + eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice[]) { let renderers = new Set(); let outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 136a5c32137..b290161bec2 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -41,6 +41,9 @@ const CANCEL_CELL_COMMAND_ID = 'workbench.notebook.cell.cancelExecution'; const EXECUTE_NOTEBOOK_COMMAND_ID = 'workbench.notebook.executeNotebook'; const CANCEL_NOTEBOOK_COMMAND_ID = 'workbench.notebook.cancelExecution'; +const CLEAR_CELL_OUTPUTS_COMMAND_ID = 'workbench.action.notebook.clearCellOutputs'; +const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'workbench.action.notebook.clearAllCellsOutputs'; + const NOTEBOOK_ACTIONS_CATEGORY = localize('notebookActions.category', "Notebook"); const EDITOR_WIDGET_ACTION_WEIGHT = KeybindingWeight.EditorContrib; // smaller than Suggest Widget, etc @@ -50,6 +53,7 @@ const enum CellToolbarOrder { MoveCellDown, EditCell, SaveCell, + ClearCellOutput, InsertCell, DeleteCell } @@ -1171,3 +1175,69 @@ registerAction2(class extends Action2 { editor.focusNotebookCell(firstCell, false); } }); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: CLEAR_CELL_OUTPUTS_COMMAND_ID, + title: 'Notebook Clear Active Cell Outputs', + menu: { + id: MenuId.NotebookCellTitle, + when: ContextKeyExpr.and(NOTEBOOK_CELL_TYPE.isEqualTo('code'), NOTEBOOK_EDITOR_RUNNABLE), + order: CellToolbarOrder.ClearCellOutput + }, + icon: { id: 'codicon/clear-all' }, + f1: true + }); + } + + async run(accessor: ServicesAccessor, context?: INotebookCellActionContext): Promise { + if (!isCellActionContext(context)) { + context = getActiveCellContext(accessor); + if (!context) { + return; + } + } + + const editor = context.notebookEditor; + if (!editor.viewModel || !editor.viewModel.length) { + return; + } + + editor.viewModel.notebookDocument.clearCellOutput(context.cell.handle); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID, + title: 'Notebook Clear All Cells Outputs', + menu: { + id: MenuId.EditorTitle, + when: NOTEBOOK_EDITOR_FOCUSED, + group: 'navigation', + order: 0 + }, + icon: { id: 'codicon/clear-all' }, + f1: true + }); + } + + async run(accessor: ServicesAccessor, context?: INotebookCellActionContext): Promise { + if (!isCellActionContext(context)) { + context = getActiveCellContext(accessor); + if (!context) { + return; + } + } + + const editor = context.notebookEditor; + if (!editor.viewModel || !editor.viewModel.length) { + return; + } + + editor.viewModel.notebookDocument.clearAllCellOutputs(); + } +}); + diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index a99c845be18..a4c27c6fc7b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -466,9 +466,10 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const scrollTop = this.list?.scrollTop || 0; const scrollHeight = this.list?.scrollHeight || 0; this.webview!.element.style.height = `${scrollHeight}px`; - let updateItems: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[] = []; if (this.webview?.insetMapping) { + let updateItems: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[] = []; + let removedItems: IOutput[] = []; this.webview?.insetMapping.forEach((value, key) => { const cell = value.cell; const viewIndex = this.list?.getViewIndex(cell); @@ -477,6 +478,11 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { return; } + if (cell.outputs.indexOf(key) < 0) { + // output is already gone + removedItems.push(key); + } + const cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0; if (this.webview!.shouldUpdateInset(cell, key, cellTop)) { updateItems.push({ @@ -487,6 +493,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } }); + removedItems.forEach(output => this.webview?.removeInset(output)); + if (updateItems.length) { this.webview?.updateViewScrollTop(-scrollTop, updateItems); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index c1522c4bb6d..59e92fafe44 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -286,6 +286,28 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel cell?.spliceNotebookCellOutputs(splices); } + clearCellOutput(handle: number) { + let cell = this._mapping.get(handle); + if (cell) { + cell.spliceNotebookCellOutputs([ + [0, cell.outputs.length, []] + ]); + + this._increaseVersionId(); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellClearOutput, versionId: this._versionId, index: this.cells.indexOf(cell) }); + } + } + + clearAllCellOutputs() { + this.cells.forEach(cell => { + cell.spliceNotebookCellOutputs([ + [0, cell.outputs.length, []] + ]); + }); + this._increaseVersionId(); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellsClearOutput, versionId: this._versionId }); + } + dispose() { this._onWillDispose.fire(); this._cellListeners.forEach(val => val.dispose()); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 7551568c6b6..009384d630c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -219,7 +219,9 @@ export type NotebookCellsSplice2 = [ export enum NotebookCellsChangeType { ModelChange = 1, - Move = 2 + Move = 2, + CellClearOutput = 3, + CellsClearOutput = 4 } export interface NotebookCellsModelChangedEvent { @@ -235,7 +237,18 @@ export interface NotebookCellsModelMoveEvent { readonly versionId: number; } -export type NotebookCellsChangedEvent = NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent; +export interface NotebookCellClearOutputEvent { + readonly kind: NotebookCellsChangeType.CellClearOutput; + readonly index: number; + readonly versionId: number; +} + +export interface NotebookCellsClearOutputEvent { + readonly kind: NotebookCellsChangeType.CellsClearOutput; + readonly versionId: number; +} + +export type NotebookCellsChangedEvent = NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent; export enum CellEditType { Insert = 1, Delete = 2 -- GitLab