parent
c905403afc
commit
0ab9d9926d
2 changed files with 51 additions and 43 deletions
|
@ -257,6 +257,30 @@ suite('Notebook API tests', function () {
|
|||
assert.strictEqual(version + 1, editor.document.version);
|
||||
});
|
||||
|
||||
test('edit API batch edits undo/redo', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
|
||||
const version = editor.document.version;
|
||||
await editor.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
|
||||
editBuilder.replaceCellMetadata(0, { inputCollapsed: false });
|
||||
});
|
||||
|
||||
await cellsChangeEvent;
|
||||
await cellMetadataChangeEvent;
|
||||
assert.strictEqual(editor.document.cellCount, 3);
|
||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, false);
|
||||
assert.strictEqual(version + 1, editor.document.version);
|
||||
|
||||
await vscode.commands.executeCommand('undo');
|
||||
assert.strictEqual(version + 2, editor.document.version);
|
||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, undefined);
|
||||
assert.strictEqual(editor.document.cellCount, 2);
|
||||
});
|
||||
|
||||
test('#98841, initialzation should not emit cell change events.', async function () {
|
||||
let count = 0;
|
||||
|
||||
|
|
|
@ -11,27 +11,16 @@ import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
|||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CellEditState, getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget';
|
||||
|
||||
class NotebookUndoRedoContribution extends Disposable {
|
||||
|
||||
constructor(@IEditorService private readonly _editorService: IEditorService) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* The undo/redo priority needs to be above code editors due to how the undo redo service works. Say we have two cells, cell 0 and cell 100, which can't be rendered in the same viewport
|
||||
* 1. focus cell 0, type
|
||||
* 2. focus cell 100. Cell 0 becomes invisible, the text model for it is disposed, which will mark the undo element "invalid"
|
||||
* 3. undo. Since the last undo element is invalid, it will remove this undo element directly other than performing any real undo.
|
||||
*
|
||||
* We now make the notebook undo/redo impl the highest priority so we don't skip the "invalid" undo/redo element in the same notebook document
|
||||
*/
|
||||
this._register(UndoCommand.addImplementation(10000 + 5, 'notebook-undo-redo', () => {
|
||||
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane) as NotebookEditorWidget | undefined;
|
||||
if (editor?.hasModel()) {
|
||||
const activeCodeEditor = editor.activeCodeEditor;
|
||||
|
||||
if ((activeCodeEditor && activeCodeEditor.hasTextFocus()) || !activeCodeEditor) {
|
||||
const PRIORITY = 105;
|
||||
this._register(UndoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
|
||||
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
|
||||
if (editor?.viewModel) {
|
||||
return editor.viewModel.undo().then(cellResources => {
|
||||
if (cellResources?.length) {
|
||||
editor?.viewModel?.viewCells.forEach(cell => {
|
||||
|
@ -44,17 +33,13 @@ class NotebookUndoRedoContribution extends Disposable {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}));
|
||||
|
||||
this._register(RedoCommand.addImplementation(10000 + 5, 'notebook-undo-redo', () => {
|
||||
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane) as NotebookEditorWidget | undefined;
|
||||
if (editor?.hasModel()) {
|
||||
const activeCodeEditor = editor.activeCodeEditor;
|
||||
|
||||
if ((activeCodeEditor && activeCodeEditor.hasTextFocus()) || !activeCodeEditor) {
|
||||
this._register(RedoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
|
||||
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
|
||||
if (editor?.viewModel) {
|
||||
return editor.viewModel.redo().then(cellResources => {
|
||||
if (cellResources?.length) {
|
||||
editor?.viewModel?.viewCells.forEach(cell => {
|
||||
|
@ -67,7 +52,6 @@ class NotebookUndoRedoContribution extends Disposable {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}));
|
||||
|
|
Loading…
Reference in a new issue