remove notebookEditor.createCell

This commit is contained in:
rebornix
2021-09-15 16:26:59 -07:00
parent 4fcbe9449c
commit f5dcfe5e08
7 changed files with 113 additions and 83 deletions
@@ -7,12 +7,13 @@ import { IBulkEditService, ResourceEdit, ResourceTextEdit } from 'vs/editor/brow
import { IPosition, Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { EndOfLinePreference, IReadonlyTextBuffer } from 'vs/editor/common/model';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
import { INotebookActionContext, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { CellEditState, CellFocusMode, expandCellRangesWithHiddenCells, IActiveNotebookEditor, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { cloneNotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { CellEditType, CellKind, ICellEditOperation, ICellReplaceEdit, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, CellKind, ICellEditOperation, ICellReplaceEdit, IOutputDto, ISelectionState, NotebookCellMetadata, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { cellRangeContains, cellRangesToIndexes, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
export async function changeCellToKind(kind: CellKind, context: INotebookActionContext, language?: string, mime?: string): Promise<void> {
@@ -571,3 +572,79 @@ export function computeCellLinesContents(cell: ICellViewModel, splitPoints: IPos
return newLineModels;
}
export function insertCell(
modeService: IModeService,
editor: IActiveNotebookEditor,
cell: ICellViewModel | undefined,
type: CellKind,
direction: 'above' | 'below' = 'above',
initialText: string = '',
ui: boolean = false
) {
const viewModel = editor._getViewModel();
const activeKernel = editor.activeKernel;
if (viewModel.options.isReadOnly) {
return null;
}
const index = cell ? viewModel.getCellIndex(cell) : 0;
const nextIndex = ui ? viewModel.getNextVisibleCellIndex(index) : index + 1;
let language;
if (type === CellKind.Code) {
const supportedLanguages = activeKernel?.supportedLanguages ?? modeService.getRegisteredModes();
const defaultLanguage = supportedLanguages[0] || 'plaintext';
if (cell?.cellKind === CellKind.Code) {
language = cell.language;
} else if (cell?.cellKind === CellKind.Markup) {
const nearestCodeCellIndex = viewModel.nearestCodeCellIndex(index);
if (nearestCodeCellIndex > -1) {
language = viewModel.cellAt(nearestCodeCellIndex)!.language;
} else {
language = defaultLanguage;
}
} else {
if (cell === undefined && direction === 'above') {
// insert cell at the very top
language = viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || defaultLanguage;
} else {
language = defaultLanguage;
}
}
if (!supportedLanguages.includes(language)) {
// the language no longer exists
language = defaultLanguage;
}
} else {
language = 'markdown';
}
const insertIndex = cell ?
(direction === 'above' ? index : nextIndex) :
index;
return insertCellAtIndex(viewModel, insertIndex, initialText, language, type, undefined, [], true);
}
export function insertCellAtIndex(viewModel: NotebookViewModel, index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, outputs: IOutputDto[], synchronous: boolean, pushUndoStop: boolean = true): CellViewModel {
const endSelections: ISelectionState = { kind: SelectionStateType.Index, focus: { start: index, end: index + 1 }, selections: [{ start: index, end: index + 1 }] };
viewModel.notebookDocument.applyEdits([
{
editType: CellEditType.Replace,
index,
count: 0,
cells: [
{
cellKind: type,
language: language,
mime: undefined,
outputs: outputs,
metadata: metadata,
source: source
}
]
}
], synchronous, { kind: SelectionStateType.Index, focus: viewModel.getFocus(), selections: viewModel.getSelections() }, () => endSelections, undefined, pushUndoStop);
return viewModel.cellAt(index)!;
}
@@ -7,11 +7,13 @@ import { maxIndex, minIndex } from 'vs/base/common/arrays';
import { Iterable } from 'vs/base/common/iterator';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IModeService } from 'vs/editor/common/services/modeService';
import { localize } from 'vs/nls';
import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { EditorsOrder } from 'vs/workbench/common/editor';
import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
import { cellExecutionArgs, CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, executeNotebookCondition, getContextFromActiveEditor, getContextFromUri, INotebookActionContext, INotebookCellActionContext, INotebookCellToolbarActionContext, INotebookCommandContext, NotebookAction, NotebookCellAction, NotebookMultiCellAction, NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT, parseMultiCellExecutionArgs } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_MISSING_KERNEL_EXTENSION } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
@@ -407,6 +409,7 @@ registerAction2(class ExecuteCellSelectBelow extends NotebookCellAction {
if (typeof idx !== 'number') {
return;
}
const modeService = accessor.get(IModeService);
if (context.cell.cellKind === CellKind.Markup) {
const nextCell = context.notebookEditor.cellAt(idx + 1);
@@ -414,7 +417,8 @@ registerAction2(class ExecuteCellSelectBelow extends NotebookCellAction {
if (nextCell) {
context.notebookEditor.focusNotebookCell(nextCell, 'container');
} else {
const newCell = context.notebookEditor.insertNotebookCell(context.cell, CellKind.Markup, 'below');
const newCell = insertCell(modeService, context.notebookEditor, context.cell, CellKind.Markup, 'below');
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
@@ -426,7 +430,8 @@ registerAction2(class ExecuteCellSelectBelow extends NotebookCellAction {
if (nextCell) {
context.notebookEditor.focusNotebookCell(nextCell, 'container');
} else {
const newCell = context.notebookEditor.insertNotebookCell(context.cell, CellKind.Code, 'below');
const newCell = insertCell(modeService, context.notebookEditor, context.cell, CellKind.Code, 'below');
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
@@ -452,10 +457,11 @@ registerAction2(class ExecuteCellInsertBelow extends NotebookCellAction {
}
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
const modeService = accessor.get(IModeService);
const newFocusMode = context.cell.focusMode === CellFocusMode.Editor ? 'editor' : 'container';
const executionP = runCell(accessor, context);
const newCell = context.notebookEditor.insertNotebookCell(context.cell, CellKind.Code, 'below');
const newCell = insertCell(modeService, context.notebookEditor, context.cell, CellKind.Code, 'below');
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, newFocusMode);
}
@@ -5,12 +5,14 @@
import { Codicon } from 'vs/base/common/codicons';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IModeService } from 'vs/editor/common/services/modeService';
import { localize } from 'vs/nls';
import { IAction2Options, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
import { INotebookActionContext, NotebookAction } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_EDITOR_EDITABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
@@ -41,12 +43,13 @@ abstract class InsertCellCommand extends NotebookAction {
context.notebookEditor.focus();
}
const modeService = accessor.get(IModeService);
if (context.cell) {
newCell = context.notebookEditor.insertNotebookCell(context.cell, this.kind, this.direction, undefined, true);
newCell = insertCell(modeService, context.notebookEditor, context.cell, this.kind, this.direction, undefined, true);
} else {
const focusRange = context.notebookEditor.getFocus();
const next = focusRange.end - 1;
newCell = context.notebookEditor.insertNotebookCell(context.notebookEditor.cellAt(next), this.kind, this.direction, undefined, true);
newCell = insertCell(modeService, context.notebookEditor, context.notebookEditor.cellAt(next), this.kind, this.direction, undefined, true);
}
if (newCell) {
@@ -181,7 +184,9 @@ registerAction2(class InsertCodeCellAtTopAction extends NotebookAction {
}
async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
const newCell = context.notebookEditor.insertNotebookCell(undefined, CellKind.Code, 'above', undefined, true);
const modeService = accessor.get(IModeService);
const newCell = insertCell(modeService, context.notebookEditor, undefined, CellKind.Code, 'above', undefined, true);
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
@@ -206,7 +211,9 @@ registerAction2(class InsertMarkdownCellAtTopAction extends NotebookAction {
}
async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
const newCell = context.notebookEditor.insertNotebookCell(undefined, CellKind.Markup, 'above', undefined, true);
const modeService = accessor.get(IModeService);
const newCell = insertCell(modeService, context.notebookEditor, undefined, CellKind.Markup, 'above', undefined, true);
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
@@ -464,11 +464,6 @@ export interface INotebookEditor {
*/
getOutputRenderer(): OutputRenderer;
/**
* Insert a new cell around `cell`
*/
insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction?: 'above' | 'below', initialText?: string, ui?: boolean): CellViewModel | null;
/**
* Focus the container of a cell (the monaco editor inside is not focused).
*/
@@ -2017,63 +2017,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
return new Promise(resolve => { r = resolve; });
}
private _nearestCodeCellIndex(index: number /* exclusive */) {
if (!this.viewModel) {
return -1;
}
return this.viewModel.nearestCodeCellIndex(index);
}
insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction: 'above' | 'below' = 'above', initialText: string = '', ui: boolean = false): CellViewModel | null {
if (!this.viewModel) {
return null;
}
if (this.viewModel.options.isReadOnly) {
return null;
}
const index = cell ? this.viewModel.getCellIndex(cell) : 0;
const nextIndex = ui ? this.viewModel.getNextVisibleCellIndex(index) : index + 1;
let language;
if (type === CellKind.Code) {
const supportedLanguages = this.activeKernel?.supportedLanguages ?? this.modeService.getRegisteredModes();
const defaultLanguage = supportedLanguages[0] || 'plaintext';
if (cell?.cellKind === CellKind.Code) {
language = cell.language;
} else if (cell?.cellKind === CellKind.Markup) {
const nearestCodeCellIndex = this._nearestCodeCellIndex(index);
if (nearestCodeCellIndex > -1) {
language = this.viewModel.cellAt(nearestCodeCellIndex)!.language;
} else {
language = defaultLanguage;
}
} else {
if (cell === undefined && direction === 'above') {
// insert cell at the very top
language = this.viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || defaultLanguage;
} else {
language = defaultLanguage;
}
}
if (!supportedLanguages.includes(language)) {
// the language no longer exists
language = defaultLanguage;
}
} else {
language = 'markdown';
}
const insertIndex = cell ?
(direction === 'above' ? index : nextIndex) :
index;
const focused = this._list.getFocusedElements();
const selections = this._list.getSelectedElements();
return this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused[0]?.handle ?? null, selections);
}
getActiveCell() {
const elements = this._list.getFocusedElements();
@@ -21,6 +21,7 @@ import { mock } from 'vs/base/test/common/mock';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { Mimes } from 'vs/base/common/mime';
import { insertCellAtIndex } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
suite('NotebookEditorKernelManager', () => {
@@ -62,7 +63,7 @@ suite('NotebookEditorKernelManager', () => {
async (viewModel) => {
const kernelManager = instantiationService.createInstance(NotebookEditorKernelManager);
const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
const cell = insertCellAtIndex(viewModel, 1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
await assertThrowsAsync(async () => await kernelManager.executeNotebookCell(cell));
});
});
@@ -74,7 +75,7 @@ suite('NotebookEditorKernelManager', () => {
kernelService.registerKernel(new TestNotebookKernel({ languages: ['testlang'] }));
const kernelManager = instantiationService.createInstance(NotebookEditorKernelManager);
const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
const cell = insertCellAtIndex(viewModel, 1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
await assertThrowsAsync(async () => await kernelManager.executeNotebookCell(cell));
});
@@ -90,7 +91,7 @@ suite('NotebookEditorKernelManager', () => {
const executeSpy = sinon.spy();
kernel.executeNotebookCellsRequest = executeSpy;
const cell = viewModel.createCell(0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
const cell = insertCellAtIndex(viewModel, 0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
await kernelManager.executeNotebookCells(viewModel.notebookDocument, [cell]);
assert.strictEqual(executeSpy.calledOnce, true);
});
@@ -121,7 +122,7 @@ suite('NotebookEditorKernelManager', () => {
let event: ISelectedNotebooksChangeEvent | undefined;
kernelService.onDidChangeSelectedNotebooks(e => event = e);
const cell = viewModel.createCell(0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true);
const cell = insertCellAtIndex(viewModel, 0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true);
await kernelManager.executeNotebookCells(viewModel.notebookDocument, [cell]);
assert.strictEqual(didExecute, true);
@@ -15,6 +15,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { insertCellAtIndex } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
import { reduceCellRanges } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
@@ -51,7 +52,7 @@ suite('NotebookViewModel', () => {
['var b = 2;', 'javascript', CellKind.Code, [], {}]
],
(editor, viewModel) => {
const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true, null, []);
const cell = insertCellAtIndex(viewModel, 1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true);
assert.strictEqual(viewModel.length, 3);
assert.strictEqual(viewModel.notebookDocument.cells.length, 3);
assert.strictEqual(viewModel.getCellIndex(cell), 1);
@@ -125,13 +126,13 @@ suite('NotebookViewModel', () => {
const lastViewCell = viewModel.cellAt(viewModel.length - 1)!;
const insertIndex = viewModel.getCellIndex(firstViewCell) + 1;
const cell = viewModel.createCell(insertIndex, 'var c = 3;', 'javascript', CellKind.Code, {}, [], true);
const cell = insertCellAtIndex(viewModel, insertIndex, 'var c = 3;', 'javascript', CellKind.Code, {}, [], true);
const addedCellIndex = viewModel.getCellIndex(cell);
viewModel.deleteCell(addedCellIndex, true);
const secondInsertIndex = viewModel.getCellIndex(lastViewCell) + 1;
const cell2 = viewModel.createCell(secondInsertIndex, 'var d = 4;', 'javascript', CellKind.Code, {}, [], true);
const cell2 = insertCellAtIndex(viewModel, secondInsertIndex, 'var d = 4;', 'javascript', CellKind.Code, {}, [], true);
assert.strictEqual(viewModel.length, 3);
assert.strictEqual(viewModel.notebookDocument.cells.length, 3);
@@ -184,7 +185,7 @@ suite('NotebookViewModel Decorations', () => {
end: 2,
});
viewModel.createCell(0, 'var d = 6;', 'javascript', CellKind.Code, {}, [], true);
insertCellAtIndex(viewModel, 0, 'var d = 6;', 'javascript', CellKind.Code, {}, [], true);
assert.deepStrictEqual(viewModel.getTrackedRange(trackedId!), {
start: 2,
@@ -198,7 +199,7 @@ suite('NotebookViewModel Decorations', () => {
end: 2
});
viewModel.createCell(3, 'var d = 7;', 'javascript', CellKind.Code, {}, [], true);
insertCellAtIndex(viewModel, 3, 'var d = 7;', 'javascript', CellKind.Code, {}, [], true);
assert.deepStrictEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,
@@ -241,14 +242,14 @@ suite('NotebookViewModel Decorations', () => {
end: 3
});
viewModel.createCell(5, 'var d = 9;', 'javascript', CellKind.Code, {}, [], true);
insertCellAtIndex(viewModel, 5, 'var d = 9;', 'javascript', CellKind.Code, {}, [], true);
assert.deepStrictEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,
end: 3
});
viewModel.createCell(4, 'var d = 10;', 'javascript', CellKind.Code, {}, [], true);
insertCellAtIndex(viewModel, 4, 'var d = 10;', 'javascript', CellKind.Code, {}, [], true);
assert.deepStrictEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,