diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index ad832593240..751d4752928 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -623,56 +623,6 @@ suite('Notebook API tests', function () { }); }); - test('notebook workspace edit and undo redo', async function () { - const notebook = await openRandomNotebookDocument(); - const editor = await vscode.window.showNotebookDocument(notebook); - assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first'); - assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test'); - assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript'); - - await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.strictEqual(getFocusedCell(editor)?.document.getText(), ''); - - await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = getFocusedCell(editor); - assert.notStrictEqual(getFocusedCell(editor), undefined); - assert.strictEqual(activeCell!.document.getText(), ''); - assert.strictEqual(editor.document.cellCount, 4); - assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1); - - { - // modify the second cell, delete it - const edit = new vscode.WorkspaceEdit(); - edit.insert(getFocusedCell(editor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;'); - await vscode.workspace.applyEdit(edit); - } - - { - const focusedCell = getFocusedCell(editor); - assert.strictEqual(focusedCell !== undefined, true); - // delete focused cell - const edit = new vscode.WorkspaceEdit(); - edit.replaceNotebookCells(focusedCell!.notebook.uri, new vscode.NotebookRange(focusedCell!.index, focusedCell!.index + 1), []); - await vscode.workspace.applyEdit(edit); - } - - assert.strictEqual(editor.document.cellCount, 3); - assert.strictEqual(editor.document.getCells().indexOf(getFocusedCell(editor)!), 1); - - - // undo should bring back the deleted cell, and revert to previous content and selection - await vscode.commands.executeCommand('undo'); - assert.strictEqual(editor.document.cellCount, 4); - assert.strictEqual(editor.document.getCells().indexOf(getFocusedCell(editor)!), 1); - assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'var abc = 0;'); - - // redo - // await vscode.commands.executeCommand('notebook.redo'); - // assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 2); - // assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1); - // assert.strictEqual(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); - }); - test('multiple tabs: dirty + clean', async function () { const notebook = await openRandomNotebookDocument(); await vscode.window.showNotebookDocument(notebook); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 3128be19432..0f861f8903b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -308,14 +308,15 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD for (let i = 0; i < e.rawEvents.length; i++) { const change = e.rawEvents[i]; let changes: NotebookCellTextModelSplice[] = []; + const synchronous = e.synchronous ?? true; if (change.kind === NotebookCellsChangeType.ModelChange || change.kind === NotebookCellsChangeType.Initialize) { changes = change.changes; - compute(changes, e.synchronous); + compute(changes, synchronous); continue; } else if (change.kind === NotebookCellsChangeType.Move) { - compute([[change.index, change.length, []]], e.synchronous); - compute([[change.newIdx, 0, change.cells]], e.synchronous); + compute([[change.index, change.length, []]], synchronous); + compute([[change.newIdx, 0, change.cells]], synchronous); } else { continue; } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 25a651df040..ca79bc1d4cc 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { flatten } from 'vs/base/common/arrays'; -import { Emitter, Event } from 'vs/base/common/event'; +import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event'; import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata, NotebookTextModelWillAddRemoveEvent, NotebookCellTextModelSplice, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata, NotebookTextModelWillAddRemoveEvent, NotebookCellTextModelSplice, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement, UndoRedoGroup, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo'; import { MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit'; import { ISequence, LcsDiff } from 'vs/base/common/diff/diff'; @@ -32,10 +32,10 @@ class StackOperation implements IWorkspaceUndoRedoElement { private _resultAlternativeVersionId: string; constructor( - readonly resource: URI, + readonly textModel: NotebookTextModel, readonly label: string, readonly undoRedoGroup: UndoRedoGroup | undefined, - private _delayedEmitter: DelayedEmitter, + private _pauseableEmitter: PauseableEmitter, private _postUndoRedo: (alternativeVersionId: string) => void, selectionState: ISelectionState | undefined, beginAlternativeVersionId: string @@ -46,7 +46,7 @@ class StackOperation implements IWorkspaceUndoRedoElement { this._resultAlternativeVersionId = beginAlternativeVersionId; } get resources(): readonly URI[] { - return [this.resource]; + return [this.textModel.uri]; } get isEmpty(): boolean { @@ -67,30 +67,43 @@ class StackOperation implements IWorkspaceUndoRedoElement { } async undo(): Promise { - this._delayedEmitter.beginDeferredEmit(); + this._pauseableEmitter.pause(); for (let i = this._operations.length - 1; i >= 0; i--) { await this._operations[i].undo(); } this._postUndoRedo(this._beginAlternativeVersionId); - this._delayedEmitter.endDeferredEmit(this._beginSelectionState); + this._pauseableEmitter.fire({ + rawEvents: [], + synchronous: undefined, + versionId: this.textModel.versionId, + endSelectionState: this._beginSelectionState + }); + this._pauseableEmitter.resume(); } async redo(): Promise { - this._delayedEmitter.beginDeferredEmit(); + this._pauseableEmitter.pause(); for (let i = 0; i < this._operations.length; i++) { await this._operations[i].redo(); } this._postUndoRedo(this._resultAlternativeVersionId); - this._delayedEmitter.endDeferredEmit(this._resultSelectionState); + this._pauseableEmitter.fire({ + rawEvents: [], + synchronous: undefined, + versionId: this.textModel.versionId, + endSelectionState: this._resultSelectionState + }); + this._pauseableEmitter.resume(); + } } export class NotebookOperationManager { private _pendingStackOperation: StackOperation | null = null; constructor( + private readonly _textModel: NotebookTextModel, private _undoService: IUndoRedoService, - private _resource: URI, - private _delayedEmitter: DelayedEmitter, + private _pauseableEmitter: PauseableEmitter, private _postUndoRedo: (alternativeVersionId: string) => void ) { } @@ -109,7 +122,7 @@ export class NotebookOperationManager { return; } - this._pendingStackOperation = new StackOperation(this._resource, label, undoRedoGroup, this._delayedEmitter, this._postUndoRedo, selectionState, alternativeVersionId); + this._pendingStackOperation = new StackOperation(this._textModel, label, undoRedoGroup, this._pauseableEmitter, this._postUndoRedo, selectionState, alternativeVersionId); } pushEditOperation(element: IUndoRedoElement, beginSelectionState: ISelectionState | undefined, resultSelectionState: ISelectionState | undefined) { @@ -122,71 +135,6 @@ export class NotebookOperationManager { } } -class DelayedEmitter { - private _deferredCnt: number = 0; - private _notebookTextModelChangedEvent: NotebookTextModelChangedEvent | null = null; - constructor( - private readonly _onDidChangeContent: Emitter, - private readonly _textModel: NotebookTextModel - - ) { - - } - - beginDeferredEmit(): void { - this._deferredCnt++; - } - - endDeferredEmit(endSelections: ISelectionState | undefined): void { - this._deferredCnt--; - if (this._deferredCnt === 0) { - if (this._notebookTextModelChangedEvent) { - this._onDidChangeContent.fire( - { - rawEvents: this._notebookTextModelChangedEvent.rawEvents, - versionId: this._textModel.versionId, - endSelectionState: endSelections, - synchronous: this._notebookTextModelChangedEvent.synchronous - } - ); - } - - this._notebookTextModelChangedEvent = null; - } - } - - - emit(data: NotebookRawContentEvent, synchronous: boolean, endSelections?: ISelectionState) { - if (this._deferredCnt === 0) { - this._onDidChangeContent.fire( - { - rawEvents: [data], - versionId: this._textModel.versionId, - synchronous, - endSelectionState: endSelections - } - ); - } else { - if (!this._notebookTextModelChangedEvent) { - this._notebookTextModelChangedEvent = { - rawEvents: [data], - versionId: this._textModel.versionId, - endSelectionState: endSelections, - synchronous: synchronous - }; - } else { - // merge - this._notebookTextModelChangedEvent = { - rawEvents: [...this._notebookTextModelChangedEvent.rawEvents, data], - versionId: this._textModel.versionId, - endSelectionState: endSelections !== undefined ? endSelections : this._notebookTextModelChangedEvent.endSelectionState, - synchronous: synchronous - }; - } - } - } -} - type TransformedEdit = { edit: ICellEditOperation; cellIndex: number; @@ -220,7 +168,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel */ private _alternativeVersionId: string = '1'; private _operationManager: NotebookOperationManager; - private _eventEmitter: DelayedEmitter; + private _pauseableEmitter: PauseableEmitter; get length() { return this._cells.length; @@ -269,15 +217,36 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }; this._register(_modelService.onModelAdded(e => maybeUpdateCellTextModel(e))); - this._eventEmitter = new DelayedEmitter( - this._onDidChangeContent, - this - ); + this._pauseableEmitter = new PauseableEmitter({ + merge: (events: NotebookTextModelChangedEvent[]) => { + let first = events[0]; + + let rawEvents = first.rawEvents; + let versionId = first.versionId; + let endSelectionState = first.endSelectionState; + let synchronous = first.synchronous; + + for (let i = 1; i < events.length; i++) { + rawEvents.push(...events[i].rawEvents); + versionId = events[i].versionId; + endSelectionState = events[i].endSelectionState !== undefined ? events[i].endSelectionState : endSelectionState; + synchronous = events[i].synchronous !== undefined ? events[i].synchronous : synchronous; + } + + return { rawEvents, versionId, endSelectionState, synchronous }; + } + }); + + this._register(this._pauseableEmitter.event(e => { + if (e.rawEvents.length) { + this._onDidChangeContent.fire(e); + } + })); this._operationManager = new NotebookOperationManager( + this, this._undoService, - uri, - this._eventEmitter, + this._pauseableEmitter, (alternativeVersionId: string) => { this._increaseVersionId(true); this._overwriteAlternativeVersionId(alternativeVersionId); @@ -308,7 +277,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._alternativeVersionId = this._generateAlternativeId(); if (triggerDirty) { - this._eventEmitter.emit({ kind: NotebookCellsChangeType.Unknown, transient: false }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.Unknown, transient: false }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } } @@ -316,15 +290,30 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._increaseVersionId(e === 'content'); switch (e) { case 'content': - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeCellContent, transient: false }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeCellContent, transient: false }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); break; case 'language': - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeLanguage, index: this._getCellIndexByHandle(cell.handle), language: cell.language, transient: false }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeLanguage, index: this._getCellIndexByHandle(cell.handle), language: cell.language, transient: false }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); break; case 'mime': - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeCellMime, index: this._getCellIndexByHandle(cell.handle), mime: cell.mime, transient: false }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeCellMime, index: this._getCellIndexByHandle(cell.handle), mime: cell.mime, transient: false }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); break; } } @@ -367,8 +356,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } applyEdits(rawEdits: ICellEditOperation[], synchronous: boolean, beginSelectionState: ISelectionState | undefined, endSelectionsComputer: () => ISelectionState | undefined, undoRedoGroup: UndoRedoGroup | undefined, computeUndoRedo: boolean = true): boolean { - - this._eventEmitter.beginDeferredEmit(); + this._pauseableEmitter.pause(); this.pushStackElement('edit', beginSelectionState, undoRedoGroup); try { @@ -383,7 +371,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.pushStackElement('edit', endSelections, undefined); // Broadcast changes - this._eventEmitter.endDeferredEmit(endSelections); + this._pauseableEmitter.fire({ rawEvents: [], versionId: this.versionId, synchronous: synchronous, endSelectionState: endSelections }); + this._pauseableEmitter.resume(); } } @@ -604,11 +593,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } // should be deferred - this._eventEmitter.emit({ - kind: NotebookCellsChangeType.ModelChange, - changes: diffs, - transient: false - }, synchronous); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ModelChange, changes: diffs, transient: false }], + versionId: this.versionId, + synchronous: synchronous, + endSelectionState: undefined + }); } private _increaseVersionId(undoStackEmpty: boolean): void { @@ -659,7 +649,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } this.metadata = metadata; - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, metadata: this.metadata, transient: this._isDocumentMetadataChangeTransient(oldMetadata, metadata) }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeDocumentMetadata, metadata: this.metadata, transient: this._isDocumentMetadataChangeTransient(oldMetadata, metadata) }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean, endSelections: ISelectionState | undefined): void { @@ -674,11 +669,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const changes: NotebookCellTextModelSplice[] = [[index, 0, cells]]; this._onWillAddRemoveCells.fire({ rawEvent: { kind: NotebookCellsChangeType.ModelChange, changes } }); this._cells.splice(index, 0, ...cells); - this._eventEmitter.emit({ - kind: NotebookCellsChangeType.ModelChange, - changes, - transient: false - }, synchronous, endSelections); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ModelChange, changes, transient: false }], + versionId: this.versionId, + synchronous: synchronous, + endSelectionState: endSelections + }); return; } @@ -692,7 +688,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const changes: NotebookCellTextModelSplice[] = [[index, count, []]]; this._onWillAddRemoveCells.fire({ rawEvent: { kind: NotebookCellsChangeType.ModelChange, changes } }); this._cells.splice(index, count); - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ModelChange, changes, transient: false }, synchronous, endSelections); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ModelChange, changes, transient: false }], + versionId: this.versionId, + synchronous: synchronous, + endSelectionState: endSelections + }); } private _replaceNewCells(index: number, count: number, cells: NotebookCellTextModel[], synchronous: boolean, endSelections: ISelectionState | undefined) { @@ -713,8 +714,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const changes: NotebookCellTextModelSplice[] = [[index, count, cells]]; this._onWillAddRemoveCells.fire({ rawEvent: { kind: NotebookCellsChangeType.ModelChange, changes } }); this._cells.splice(index, count, ...cells); - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ModelChange, changes, transient: false }, synchronous, endSelections); - + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ModelChange, changes, transient: false }], + versionId: this.versionId, + synchronous: synchronous, + endSelectionState: endSelections + }); } private _isDocumentMetadataChanged(a: NotebookDocumentMetadata, b: NotebookDocumentMetadata) { @@ -814,8 +819,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // should be deferred cell.metadata = metadata; - - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeCellMetadata, index: this._cells.indexOf(cell), metadata: cell.metadata, transient: !triggerDirtyChange }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeCellMetadata, index: this._cells.indexOf(cell), metadata: cell.metadata, transient: !triggerDirtyChange }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _changeCellInternalMetadataPartial(cell: NotebookCellTextModel, internalMetadata: NullablePartialNotebookCellInternalMetadata) { @@ -829,7 +838,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } cell.internalMetadata = newInternalMetadata; - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeCellInternalMetadata, index: this._cells.indexOf(cell), internalMetadata: cell.internalMetadata, transient: true }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeCellInternalMetadata, index: this._cells.indexOf(cell), internalMetadata: cell.internalMetadata, transient: true }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _changeCellLanguage(cell: NotebookCellTextModel, languageId: string, computeUndoRedo: boolean) { @@ -857,7 +871,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }(), undefined, undefined); } - this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeLanguage, index: this._cells.indexOf(cell), language: languageId, transient: false }, true, undefined); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.ChangeLanguage, index: this._cells.indexOf(cell), language: languageId, transient: false }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _spliceNotebookCellOutputs2(cell: NotebookCellTextModel, outputs: ICellOutput[], computeUndoRedo: boolean): void { @@ -880,14 +899,18 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private _spliceNotebookCellOutputs(cell: NotebookCellTextModel, splice: NotebookCellOutputsSplice, append: boolean, computeUndoRedo: boolean): void { cell.spliceNotebookCellOutputs(splice); - - this._eventEmitter.emit({ - kind: NotebookCellsChangeType.Output, - index: this._cells.indexOf(cell), - outputs: cell.outputs ?? [], - append, - transient: this.transientOptions.transientOutputs, - }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ + kind: NotebookCellsChangeType.Output, + index: this._cells.indexOf(cell), + outputs: cell.outputs ?? [], + append, + transient: this.transientOptions.transientOutputs, + }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _appendNotebookCellOutputItems(cell: NotebookCellTextModel, outputId: string, items: IOutputItemDto[]) { @@ -899,14 +922,20 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const output = cell.outputs[outputIndex]; output.appendData(items); - this._eventEmitter.emit({ - kind: NotebookCellsChangeType.OutputItem, - index: this._cells.indexOf(cell), - outputId: output.outputId, - outputItems: items, - append: true, - transient: this.transientOptions.transientOutputs - }, true); + this._pauseableEmitter.fire({ + rawEvents: [{ + kind: NotebookCellsChangeType.OutputItem, + index: this._cells.indexOf(cell), + outputId: output.outputId, + outputItems: items, + append: true, + transient: this.transientOptions.transientOutputs + + }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _replaceNotebookCellOutputItems(cell: NotebookCellTextModel, outputId: string, items: IOutputItemDto[]) { @@ -918,14 +947,20 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const output = cell.outputs[outputIndex]; output.replaceData(items); - this._eventEmitter.emit({ - kind: NotebookCellsChangeType.OutputItem, - index: this._cells.indexOf(cell), - outputId: output.outputId, - outputItems: items, - append: false, - transient: this.transientOptions.transientOutputs - }, true, undefined); + this._pauseableEmitter.fire({ + rawEvents: [{ + kind: NotebookCellsChangeType.OutputItem, + index: this._cells.indexOf(cell), + outputId: output.outputId, + outputItems: items, + append: false, + transient: this.transientOptions.transientOutputs + + }], + versionId: this.versionId, + synchronous: true, + endSelectionState: undefined + }); } private _moveCellToIdx(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: ISelectionState | undefined, endSelections: ISelectionState | undefined): boolean { @@ -942,7 +977,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cells = this._cells.splice(index, length); this._cells.splice(newIdx, 0, ...cells); - this._eventEmitter.emit({ kind: NotebookCellsChangeType.Move, index, length, newIdx, cells, transient: false }, synchronous, endSelections); + this._pauseableEmitter.fire({ + rawEvents: [{ kind: NotebookCellsChangeType.Move, index, length, newIdx, cells, transient: false }], + versionId: this.versionId, + synchronous: synchronous, + endSelectionState: endSelections + }); return true; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 62e1f558afd..7a2ad86414e 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -344,7 +344,7 @@ export type ISelectionState = ISelectionHandleState | ISelectionIndexState; export type NotebookTextModelChangedEvent = { readonly rawEvents: NotebookRawContentEvent[]; readonly versionId: number; - readonly synchronous: boolean; + readonly synchronous: boolean | undefined; readonly endSelectionState: ISelectionState | undefined; };