@@ -15,10 +15,8 @@ import 'vs/css!./media/notebook';
1515import { ICodeEditor } from 'vs/editor/browser/editorBrowser' ;
1616import { IEditorOptions } from 'vs/editor/common/config/editorOptions' ;
1717import { BareFontInfo } from 'vs/editor/common/config/fontInfo' ;
18- import { IPosition , Position } from 'vs/editor/common/core/position' ;
1918import { Range } from 'vs/editor/common/core/range' ;
2019import { IEditor } from 'vs/editor/common/editorCommon' ;
21- import { IReadonlyTextBuffer } from 'vs/editor/common/model' ;
2220import * as nls from 'vs/nls' ;
2321import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
2422import { IContextKey , IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
@@ -30,7 +28,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic
3028import { EditorMemento } from 'vs/workbench/browser/parts/editor/baseEditor' ;
3129import { EditorOptions , IEditorMemento } from 'vs/workbench/common/editor' ;
3230import { CELL_MARGIN , CELL_RUN_GUTTER , EDITOR_BOTTOM_PADDING , EDITOR_TOP_MARGIN , EDITOR_TOP_PADDING , SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants' ;
33- import { CellEditState , CellFocusMode , ICellRange , ICellViewModel , IEditableCellViewModel , INotebookCellList , INotebookEditor , INotebookEditorContribution , INotebookEditorMouseEvent , NotebookLayoutInfo , NOTEBOOK_EDITOR_EDITABLE , NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK , NOTEBOOK_EDITOR_FOCUSED , NOTEBOOK_EDITOR_RUNNABLE , NOTEBOOK_HAS_MULTIPLE_KERNELS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser' ;
31+ import { CellEditState , CellFocusMode , ICellRange , ICellViewModel , INotebookCellList , INotebookEditor , INotebookEditorContribution , INotebookEditorMouseEvent , NotebookLayoutInfo , NOTEBOOK_EDITOR_EDITABLE , NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK , NOTEBOOK_EDITOR_FOCUSED , NOTEBOOK_EDITOR_RUNNABLE , NOTEBOOK_HAS_MULTIPLE_KERNELS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser' ;
3432import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions' ;
3533import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList' ;
3634import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer' ;
@@ -867,175 +865,26 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
867865 return newCell ;
868866 }
869867
870- private pushIfAbsent ( positions : IPosition [ ] , p : IPosition ) {
871- const last = positions . length > 0 ? positions [ positions . length - 1 ] : undefined ;
872- if ( ! last || last . lineNumber !== p . lineNumber || last . column !== p . column ) {
873- positions . push ( p ) ;
874- }
875- }
876-
877- /**
878- * Add split point at the beginning and the end;
879- * Move end of line split points to the beginning of the next line;
880- * Avoid duplicate split points
881- */
882- private splitPointsToBoundaries ( splitPoints : IPosition [ ] , textBuffer : IReadonlyTextBuffer ) : IPosition [ ] | null {
883- const boundaries : IPosition [ ] = [ ] ;
884- const lineCnt = textBuffer . getLineCount ( ) ;
885- const getLineLen = ( lineNumber : number ) => {
886- return textBuffer . getLineLength ( lineNumber ) ;
887- } ;
888-
889- // split points need to be sorted
890- splitPoints = splitPoints . sort ( ( l , r ) => {
891- const lineDiff = l . lineNumber - r . lineNumber ;
892- const columnDiff = l . column - r . column ;
893- return lineDiff !== 0 ? lineDiff : columnDiff ;
894- } ) ;
895-
896- // eat-up any split point at the beginning, i.e. we ignore the split point at the very beginning
897- this . pushIfAbsent ( boundaries , new Position ( 1 , 1 ) ) ;
898-
899- for ( let sp of splitPoints ) {
900- if ( getLineLen ( sp . lineNumber ) + 1 === sp . column && sp . lineNumber < lineCnt ) {
901- sp = new Position ( sp . lineNumber + 1 , 1 ) ;
902- }
903- this . pushIfAbsent ( boundaries , sp ) ;
904- }
905-
906- // eat-up any split point at the beginning, i.e. we ignore the split point at the very end
907- this . pushIfAbsent ( boundaries , new Position ( lineCnt , getLineLen ( lineCnt ) + 1 ) ) ;
908-
909- // if we only have two then they describe the whole range and nothing needs to be split
910- return boundaries . length > 2 ? boundaries : null ;
911- }
912-
913- private computeCellLinesContents ( cell : IEditableCellViewModel , splitPoints : IPosition [ ] ) : string [ ] | null {
914- const rangeBoundaries = this . splitPointsToBoundaries ( splitPoints , cell . textBuffer ) ;
915- if ( ! rangeBoundaries ) {
916- return null ;
917- }
918- const newLineModels : string [ ] = [ ] ;
919- for ( let i = 1 ; i < rangeBoundaries . length ; i ++ ) {
920- const start = rangeBoundaries [ i - 1 ] ;
921- const end = rangeBoundaries [ i ] ;
922-
923- newLineModels . push ( cell . textModel . getValueInRange ( new Range ( start . lineNumber , start . column , end . lineNumber , end . column ) ) ) ;
924- }
925-
926- return newLineModels ;
927- }
928-
929868 async splitNotebookCell ( cell : ICellViewModel ) : Promise < CellViewModel [ ] | null > {
930- if ( ! this . notebookViewModel ! . metadata . editable ) {
931- return null ;
932- }
933-
934- if ( ! cell . metadata ?. editable ) {
935- return null ;
936- }
937-
938- let splitPoints = cell . getSelectionsStartPosition ( ) ;
939- if ( splitPoints && splitPoints . length > 0 ) {
940- await cell . resolveTextModel ( ) ;
941-
942- if ( ! cell . hasModel ( ) ) {
943- return null ;
944- }
945-
946- let newLinesContents = this . computeCellLinesContents ( cell , splitPoints ) ;
947- if ( newLinesContents ) {
948-
949- // update the contents of the first cell
950- cell . textModel . applyEdits ( [
951- { range : cell . textModel . getFullModelRange ( ) , text : newLinesContents [ 0 ] }
952- ] , true ) ;
953-
954- // create new cells based on the new text models
955- const language = cell . model . language ;
956- const kind = cell . cellKind ;
957- let insertIndex = this . notebookViewModel ! . getCellIndex ( cell ) + 1 ;
958- const newCells = [ ] ;
959- for ( let j = 1 ; j < newLinesContents . length ; j ++ , insertIndex ++ ) {
960- newCells . push ( this . notebookViewModel ! . createCell ( insertIndex , newLinesContents [ j ] , language , kind , true ) ) ;
961- }
962- return newCells ;
963- }
964- }
869+ const index = this . notebookViewModel ! . getCellIndex ( cell ) ;
965870
966- return null ;
871+ return this . notebookViewModel ! . splitNotebookCell ( index ) ;
967872 }
968873
969874 async joinNotebookCells ( cell : ICellViewModel , direction : 'above' | 'below' , constraint ?: CellKind ) : Promise < ICellViewModel | null > {
970- if ( ! this . notebookViewModel ! . metadata . editable ) {
971- return null ;
972- }
973-
974- if ( ! cell . getEvaluatedMetadata ( this . viewModel ! . notebookDocument . metadata ) . editable ) {
975- return null ;
976- }
977-
978- if ( constraint && cell . cellKind !== constraint ) {
979- return null ;
980- }
981-
982875 const index = this . notebookViewModel ! . getCellIndex ( cell ) ;
983- if ( index === 0 && direction === 'above' ) {
984- return null ;
985- }
986-
987- if ( index === this . notebookViewModel ! . length - 1 && direction === 'below' ) {
988- return null ;
989- }
990-
991- if ( direction === 'above' ) {
992- const above = this . notebookViewModel ! . viewCells [ index - 1 ] ;
993- if ( constraint && above . cellKind !== constraint ) {
994- return null ;
995- }
876+ const ret = await this . notebookViewModel ! . joinNotebookCells ( index , direction , constraint ) ;
996877
997- if ( ! above . getEvaluatedMetadata ( this . viewModel ! . notebookDocument . metadata ) . editable ) {
998- return null ;
999- }
878+ if ( ret ) {
879+ ret . deletedCells . forEach ( cell => {
880+ if ( this . pendingLayouts . has ( cell ) ) {
881+ this . pendingLayouts . get ( cell ) ! . dispose ( ) ;
882+ }
883+ } ) ;
1000884
1001- await above . resolveTextModel ( ) ;
1002- if ( ! above . hasModel ( ) ) {
1003- return null ;
1004- }
1005- const insertContent = ( cell . textModel ?. getEOL ( ) ?? '' ) + cell . getText ( ) ;
1006- const aboveCellLineCount = above . textModel . getLineCount ( ) ;
1007- const aboveCellLastLineEndColumn = above . textModel . getLineLength ( aboveCellLineCount ) ;
1008- above . textModel . applyEdits ( [
1009- { range : new Range ( aboveCellLineCount , aboveCellLastLineEndColumn + 1 , aboveCellLineCount , aboveCellLastLineEndColumn + 1 ) , text : insertContent }
1010- ] ) ;
1011-
1012- await this . deleteNotebookCell ( cell ) ;
1013- return above ;
885+ return ret . cell ;
1014886 } else {
1015- const below = this . notebookViewModel ! . viewCells [ index + 1 ] ;
1016- if ( constraint && below . cellKind !== constraint ) {
1017- return null ;
1018- }
1019-
1020- if ( ! below . getEvaluatedMetadata ( this . viewModel ! . notebookDocument . metadata ) . editable ) {
1021- return null ;
1022- }
1023-
1024- await cell . resolveTextModel ( ) ;
1025- if ( ! cell . hasModel ( ) ) {
1026- return null ;
1027- }
1028-
1029- const insertContent = ( cell . textModel ?. getEOL ( ) ?? '' ) + below . getText ( ) ;
1030-
1031- const cellLineCount = cell . textModel . getLineCount ( ) ;
1032- const cellLastLineEndColumn = cell . textModel . getLineLength ( cellLineCount ) ;
1033- cell . textModel . applyEdits ( [
1034- { range : new Range ( cellLineCount , cellLastLineEndColumn + 1 , cellLineCount , cellLastLineEndColumn + 1 ) , text : insertContent }
1035- ] ) ;
1036-
1037- await this . deleteNotebookCell ( below ) ;
1038- return cell ;
887+ return null ;
1039888 }
1040889 }
1041890
0 commit comments