From cd17443ae7f0ca105b9ec82ad805a57f0067af33 Mon Sep 17 00:00:00 2001 From: kieferrm Date: Sat, 25 Apr 2020 16:08:53 -0700 Subject: [PATCH 1/4] split and join --- .../notebook/browser/contrib/coreActions.ts | 96 +++++++++++++++++++ .../notebook/browser/notebookBrowser.ts | 14 +++ .../notebook/browser/notebookEditor.ts | 67 +++++++++++++ .../browser/viewModel/baseCellViewModel.ts | 17 ++++ .../notebook/test/testNotebookEditor.ts | 8 ++ 5 files changed, 202 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index ffd9043e2d534..1359453bbc26f 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -50,6 +50,9 @@ const PASTE_CELL_COMMAND_ID = 'notebook.cell.paste'; const PASTE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.pasteAbove'; const COPY_CELL_UP_COMMAND_ID = 'notebook.cell.copyUp'; const COPY_CELL_DOWN_COMMAND_ID = 'notebook.cell.copyDown'; +const SPLIT_CELL_COMMAND_ID = 'notebook.cell.split'; +const JOIN_CELL_ABOVE_COMMAND_ID = 'notebook.cell.joinAbove'; +const JOIN_CELL_BELOW_COMMAND_ID = 'notebook.cell.joinBelow'; const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute'; const CANCEL_CELL_COMMAND_ID = 'notebook.cell.cancelExecution'; @@ -66,6 +69,7 @@ const enum CellToolbarOrder { MoveCellUp, MoveCellDown, EditCell, + SplitCell, SaveCell, ClearCellOutput, InsertCell, @@ -1255,3 +1259,95 @@ registerAction2(class extends Action2 { } }); +async function splitCell(context: INotebookCellActionContext): Promise { + if (context.cell.cellKind === CellKind.Code) { + const newCells = context.notebookEditor.splitNotebookCell(context.cell); + if (newCells) { + context.notebookEditor.focusNotebookCell(newCells[newCells.length - 1], true); + } + } +} + +registerAction2(class extends Action2 { + constructor() { + super( + { + id: SPLIT_CELL_COMMAND_ID, + title: localize('notebookActions.splitCell', "Split Cell"), + category: NOTEBOOK_ACTIONS_CATEGORY, + menu: { + id: MenuId.NotebookCellTitle, + when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_CELL_TYPE.isEqualTo('code'), NOTEBOOK_EDITOR_EDITABLE, InputFocusedContext), + order: CellToolbarOrder.SplitCell + }, + icon: { id: 'codicon/split-vertical' }, + f1: true + }); + } + + async run(accessor: ServicesAccessor, context?: INotebookCellActionContext) { + if (!isCellActionContext(context)) { + context = getActiveCellContext(accessor); + if (!context) { + return; + } + } + + return splitCell(context); + } +}); + + +async function joinCells(context: INotebookCellActionContext, direction: 'above' | 'below'): Promise { + const cell = await context.notebookEditor.joinNotebookCells(context.cell, direction, CellKind.Code); + if (cell) { + context.notebookEditor.focusNotebookCell(cell, true); + } +} + +registerAction2(class extends Action2 { + constructor() { + super( + { + id: JOIN_CELL_ABOVE_COMMAND_ID, + title: localize('notebookActions.joinCellAbove', "Join with Previous Cell"), + category: NOTEBOOK_ACTIONS_CATEGORY, + f1: true + }); + } + + async run(accessor: ServicesAccessor, context?: INotebookCellActionContext) { + if (!isCellActionContext(context)) { + context = getActiveCellContext(accessor); + if (!context) { + return; + } + } + + return joinCells(context, 'above'); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super( + { + id: JOIN_CELL_BELOW_COMMAND_ID, + title: localize('notebookActions.joinCellBelow', "Join with Next Cell"), + category: NOTEBOOK_ACTIONS_CATEGORY, + f1: true + }); + } + + async run(accessor: ServicesAccessor, context?: INotebookCellActionContext) { + if (!isCellActionContext(context)) { + context = getActiveCellContext(accessor); + if (!context) { + return; + } + } + + return joinCells(context, 'below'); + } +}); + diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index aa1de467fac76..756304ded9e33 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -99,6 +99,10 @@ export interface ICellViewModel { getText(): string; metadata: NotebookCellMetadata | undefined; getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata; + + getSelectionOffsets(): number[] | undefined; + language: string; + setText(value: string[]): void; } export interface INotebookEditorMouseEvent { @@ -162,6 +166,16 @@ export interface INotebookEditor { */ insertNotebookCell(cell: ICellViewModel | undefined, type: CellKind, direction?: 'above' | 'below', initialText?: string): CellViewModel | null; + /** + * Split a given cell into multiple cells of the same type using the selection start positions. + */ + splitNotebookCell(cell: ICellViewModel): CellViewModel[] | null; + + /** + * Joins the given cell either with the cell above or the one below depending on the given direction. + */ + joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise; + /** * Delete a cell from the notebook */ diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 9df6a6d3aa986..890c87abe7a7c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -729,6 +729,73 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { return newCell; } + splitNotebookCell(cell: ICellViewModel): CellViewModel[] | null { + if (!this.notebookViewModel!.metadata.editable) { + return null; + } + + const splitPoints = cell.getSelectionOffsets(); + if (splitPoints && splitPoints.length > 0) { + const cellContent = cell.getText(); + splitPoints.push(cellContent.length); + + // update the content of first cell + cell.setText(cellContent.substr(0, splitPoints[0]).split(/\r?\n/g)); + + const language = cell.model.language; + const kind = cell.cellKind; + let insertIndex = this.notebookViewModel!.getCellIndex(cell) + 1; + const newCells = []; + for (let i = 1, y = insertIndex; i < splitPoints.length; i++, y++) { + // create new cells containing the text chucks between starts of the selections + let initialText = cellContent.substring(splitPoints[i - 1], splitPoints[i]); + newCells.push(this.notebookViewModel!.createCell(y, initialText.split(/\r?\n/g), language, kind, true)); + } + return newCells; + } + + return null; + } + + async joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise { + if (!this.notebookViewModel!.metadata.editable) { + return null; + } + + if (constraint && cell.cellKind !== constraint) { + return null; + } + + const index = this.notebookViewModel!.getCellIndex(cell); + if (index === 0 && direction === 'above') { + return null; + } + + if (index === this.notebookViewModel!.length - 1 && direction === 'below') { + return null; + } + + if (direction === 'above') { + const above = this.notebookViewModel!.viewCells[index - 1]; + if (constraint && above.cellKind !== constraint) { + return null; + } + const newContent = `${above.getText()}\n${cell.getText()}`; + above.setText(newContent.split(/\r?\n/g)); + await this.deleteNotebookCell(cell); + return above; + } else { + const below = this.notebookViewModel!.viewCells[index + 1]; + if (constraint && below.cellKind !== constraint) { + return null; + } + const newContent = `${cell.getText()}\n${below.getText()}`; + cell.setText(newContent.split(/\r?\n/g)); + await this.deleteNotebookCell(below); + return cell; + } + } + async deleteNotebookCell(cell: ICellViewModel): Promise { if (!this.notebookViewModel!.metadata.editable) { return false; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 6779eb7c8d4f4..c94dab4b4655d 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -199,6 +199,14 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM return this.model.source.join('\n'); } + setText(value: string[]) { + if (this._textModel) { + return this._textModel.setValue(value.join('\n')); + } else { + this.model.source = value; + } + } + private saveViewState(): editorCommon.ICodeEditorViewState | null { if (!this._textEditor) { return null; @@ -269,6 +277,15 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM this._textEditor?.setSelection(range); } + getSelectionOffsets(): number[] | undefined { + const textModel = this._textEditor?.getModel(); + const selections = this._textEditor?.getSelections(); + if (textModel && selections) { + return selections.map(s => textModel.getOffsetAt(s.getStartPosition())); + } + return undefined; + } + getLineScrollTopOffset(line: number): number { if (!this._textEditor) { return 0; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index e319821cfa33a..100b8ced56b4d 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -117,6 +117,14 @@ export class TestNotebookEditor implements INotebookEditor { throw new Error('Method not implemented.'); } + splitNotebookCell(cell: ICellViewModel): CellViewModel[] | null { + throw new Error('Method not implemented.'); + } + + joinNotebookCells(cell: ICellViewModel, direction: 'above' | 'below', constraint?: CellKind): Promise { + throw new Error('Method not implemented.'); + } + setSelection(cell: CellViewModel, selection: Range): void { throw new Error('Method not implemented.'); } From 0d5c36bf496f6772d18dc1e6ef8d573557dd3d83 Mon Sep 17 00:00:00 2001 From: kieferrm Date: Sat, 2 May 2020 14:10:03 -0700 Subject: [PATCH 2/4] use line models (string[]) directly --- .../notebook/browser/notebookBrowser.ts | 6 +- .../notebook/browser/notebookEditor.ts | 127 +++++++++++++++--- .../browser/view/renderers/markdownCell.ts | 2 +- .../browser/viewModel/baseCellViewModel.ts | 25 +++- .../viewModel/markdownCellViewModel.ts | 2 +- 5 files changed, 131 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 756304ded9e33..30c1b8e9f3160 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -16,6 +16,7 @@ import { URI } from 'vs/base/common/uri'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { Range } from 'vs/editor/common/core/range'; +import { IPosition } from 'vs/editor/common/core/position'; import { FindMatch } from 'vs/editor/common/model'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; @@ -100,9 +101,10 @@ export interface ICellViewModel { metadata: NotebookCellMetadata | undefined; getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata; - getSelectionOffsets(): number[] | undefined; + getSelectionsStartPosition(): IPosition[] | undefined; language: string; - setText(value: string[]): void; + setLinesContent(value: string[]): void; + getLinesContent(): string[]; } export interface INotebookEditorMouseEvent { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 890c87abe7a7c..4cd1a63875595 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -45,6 +45,7 @@ import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/w import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { onUnexpectedError } from 'vs/base/common/errors'; +import { IPosition, Position } from 'vs/editor/common/core/position'; const $ = DOM.$; const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState'; @@ -729,29 +730,115 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { return newCell; } + private isAtEOL(p: IPosition, lines: string[]) { + const line = lines[p.lineNumber - 1]; + return line.length + 1 === p.column; + } + + private pushIfAbsent(positions: IPosition[], p: IPosition) { + const last = positions.length > 0 ? positions[positions.length - 1] : undefined; + if (!last || last.lineNumber !== p.lineNumber || last.column !== p.column) { + positions.push(p); + } + } + + /** + * Add split point at the beginning and the end; + * Move end of line split points to the beginning of the next line; + * Avoid duplicate split points + */ + private splitPointsToBoundaries(splitPoints: IPosition[], lines: string[]): IPosition[] | null { + const boundaries: IPosition[] = []; + + // split points need to be sorted + splitPoints = splitPoints.sort((l, r) => { + const lineDiff = l.lineNumber - r.lineNumber; + const columnDiff = l.column - r.column; + return lineDiff !== 0 ? lineDiff : columnDiff; + }); + + // eat-up any split point at the beginning, i.e. we ignore the split point at the very beginning + this.pushIfAbsent(boundaries, new Position(1, 1)); + + for (let sp of splitPoints) { + if (this.isAtEOL(sp, lines) && sp.lineNumber < lines.length) { + sp = new Position(sp.lineNumber + 1, 1); + } + this.pushIfAbsent(boundaries, sp); + } + + // eat-up any split point at the beginning, i.e. we ignore the split point at the very end + this.pushIfAbsent(boundaries, new Position(lines.length, lines[lines.length - 1].length + 1)); + + // if we only have two then they describe the whole range and nothing needs to be split + return boundaries.length > 2 ? boundaries : null; + } + + private computeCellLinesContents(cell: ICellViewModel, splitPoints: IPosition[]): string[][] | null { + const lines = cell.getLinesContent(); + const rangeBoundaries = this.splitPointsToBoundaries(splitPoints, lines); + if (!rangeBoundaries) { + return null; + } + const newLineModels: string[][] = []; + for (let i = 1; i < rangeBoundaries.length; i++) { + const start = rangeBoundaries[i - 1]; + const end = rangeBoundaries[i]; + // get the right lines + const newLines = lines.slice(start.lineNumber - 1, end.lineNumber); + if (start.lineNumber === end.lineNumber) { + // cut the line at the beginning and the end + let line = newLines[0]; + line = line.slice(start.column - 1, end.column - 1); + newLines[0] = line; + } + else { + // cut last line at the end + let lastLine = newLines[newLines.length - 1]; + lastLine = lastLine.slice(0, end.column - 1); + if (lastLine) { + newLines[newLines.length - 1] = lastLine; + } else { + newLines.pop(); + } + + // cut first line at the beginning + let firstLine = newLines[0]; + firstLine = firstLine.slice(start.column - 1); + if (firstLine) { + newLines[0] = firstLine; + } else { + newLines.shift(); + } + } + newLineModels.push(newLines); + } + return newLineModels; + } + splitNotebookCell(cell: ICellViewModel): CellViewModel[] | null { if (!this.notebookViewModel!.metadata.editable) { return null; } - const splitPoints = cell.getSelectionOffsets(); + let splitPoints = cell.getSelectionsStartPosition(); if (splitPoints && splitPoints.length > 0) { - const cellContent = cell.getText(); - splitPoints.push(cellContent.length); - - // update the content of first cell - cell.setText(cellContent.substr(0, splitPoints[0]).split(/\r?\n/g)); - - const language = cell.model.language; - const kind = cell.cellKind; - let insertIndex = this.notebookViewModel!.getCellIndex(cell) + 1; - const newCells = []; - for (let i = 1, y = insertIndex; i < splitPoints.length; i++, y++) { - // create new cells containing the text chucks between starts of the selections - let initialText = cellContent.substring(splitPoints[i - 1], splitPoints[i]); - newCells.push(this.notebookViewModel!.createCell(y, initialText.split(/\r?\n/g), language, kind, true)); + let newLinesContents = this.computeCellLinesContents(cell, splitPoints); + if (newLinesContents) { + + // update the contents of the first cell + cell.setLinesContent(newLinesContents[0]); + + // create new cells based on the new text models + const language = cell.model.language; + const kind = cell.cellKind; + let insertIndex = this.notebookViewModel!.getCellIndex(cell) + 1; + const newCells = []; + for (let j = 1; j < newLinesContents.length; j++, insertIndex++) { + newCells.push(this.notebookViewModel!.createCell(insertIndex, newLinesContents[j], language, kind, true)); + } + return newCells; } - return newCells; } return null; @@ -780,8 +867,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { if (constraint && above.cellKind !== constraint) { return null; } - const newContent = `${above.getText()}\n${cell.getText()}`; - above.setText(newContent.split(/\r?\n/g)); + const newContent = above.getLinesContent().concat(cell.getLinesContent()); + above.setLinesContent(newContent); await this.deleteNotebookCell(cell); return above; } else { @@ -789,8 +876,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { if (constraint && below.cellKind !== constraint) { return null; } - const newContent = `${cell.getText()}\n${below.getText()}`; - cell.setText(newContent.split(/\r?\n/g)); + const newContent = cell.getLinesContent().concat(below.getLinesContent()); + cell.setLinesContent(newContent); await this.deleteNotebookCell(below); return cell; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index ed496b4477247..ae6d0a95d7812 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -225,7 +225,7 @@ export class StatefullMarkdownCell extends Disposable { bindEditorListeners(model: ITextModel, dimension?: IDimension) { this.localDisposables.add(model.onDidChangeContent(() => { - this.viewCell.setText(model.getLinesContent()); + this.viewCell.setLinesContent(model.getLinesContent()); let clientHeight = this.markdownContainer.clientHeight; this.markdownContainer.innerHTML = ''; let renderedHTML = this.viewCell.getHTML(); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index c94dab4b4655d..eaeda88db087b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -8,6 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; +import { IPosition } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; @@ -199,8 +200,17 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM return this.model.source.join('\n'); } - setText(value: string[]) { + getLinesContent(): string[] { if (this._textModel) { + return this._textModel.getLinesContent(); + } + + return this.model.source; + } + + setLinesContent(value: string[]) { + if (this._textModel) { + // TODO @rebornix we should avoid creating a new string here return this._textModel.setValue(value.join('\n')); } else { this.model.source = value; @@ -277,13 +287,14 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM this._textEditor?.setSelection(range); } - getSelectionOffsets(): number[] | undefined { - const textModel = this._textEditor?.getModel(); - const selections = this._textEditor?.getSelections(); - if (textModel && selections) { - return selections.map(s => textModel.getOffsetAt(s.getStartPosition())); + getSelectionsStartPosition(): IPosition[] | undefined { + if (this._textEditor) { + const selections = this._textEditor.getSelections(); + return selections?.map(s => s.getStartPosition()); + } else { + const selections = this._editorViewStates?.cursorState; + return selections?.map(s => s.selectionStart); } - return undefined; } getLineScrollTopOffset(line: number): number { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 50eaf8429ed50..1e93626101005 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -112,7 +112,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie } } - setText(strs: string[]) { + setLinesContent(strs: string[]) { this.model.source = strs; this._html = null; } From d5fa6230d1255b6cc9ec31fee5f868aa3fbdfbe3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 4 May 2020 10:05:40 -0700 Subject: [PATCH 3/4] format --- .../contrib/notebook/browser/viewModel/baseCellViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index c2ef09b44aa57..0ff66da32b91a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -217,7 +217,7 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM } } - abstract save(): void; + abstract save(): void; private saveViewState(): void { if (!this._textEditor) { From 2d0f820d6cd8ac6c4823e5db90aca57f519156cf Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 4 May 2020 10:26:58 -0700 Subject: [PATCH 4/4] remove duplicate identifiers --- src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 747780b9a949a..c4e437ec0d897 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -106,9 +106,7 @@ export interface ICellViewModel { save(): void; metadata: NotebookCellMetadata | undefined; getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata; - getSelectionsStartPosition(): IPosition[] | undefined; - language: string; setLinesContent(value: string[]): void; getLinesContent(): string[]; }