@@ -96,6 +96,7 @@ export class NotebookMultiCursorController extends Disposable implements INotebo
96
96
position : Position ;
97
97
} | undefined ;
98
98
private trackedCells : TrackedCell [ ] ;
99
+ private totalMatchesCount : number ;
99
100
100
101
private readonly _onDidChangeAnchorCell ;
101
102
readonly onDidChangeAnchorCell : Event < void > ;
@@ -125,6 +126,7 @@ export class NotebookMultiCursorController extends Disposable implements INotebo
125
126
super ( ) ;
126
127
this . word = '' ;
127
128
this . trackedCells = [ ] ;
129
+ this . totalMatchesCount = 0 ;
128
130
this . _onDidChangeAnchorCell = this . _register ( new Emitter < void > ( ) ) ;
129
131
this . onDidChangeAnchorCell = this . _onDidChangeAnchorCell . event ;
130
132
this . anchorDisposables = this . _register ( new DisposableStore ( ) ) ;
@@ -478,6 +480,7 @@ export class NotebookMultiCursorController extends Disposable implements INotebo
478
480
this . cursorsDisposables . clear ( ) ;
479
481
this . cursorsControllers . clear ( ) ;
480
482
this . trackedCells = [ ] ;
483
+ this . totalMatchesCount = 0 ;
481
484
this . startPosition = undefined ;
482
485
this . word = '' ;
483
486
}
@@ -496,6 +499,13 @@ export class NotebookMultiCursorController extends Disposable implements INotebo
496
499
}
497
500
this . word = word . word ;
498
501
502
+ // Record the total number of matches at the beginning of the selection process for performance
503
+ const notebookTextModel = this . notebookEditor . textModel ;
504
+ if ( notebookTextModel ) {
505
+ const allMatches = notebookTextModel . findMatches ( this . word , false , true , USUAL_WORD_SEPARATORS ) ;
506
+ this . totalMatchesCount = allMatches . reduce ( ( sum , cellMatch ) => sum + cellMatch . matches . length , 0 ) ;
507
+ }
508
+
499
509
const index = this . notebookEditor . getCellIndex ( focusedCell ) ;
500
510
if ( index === undefined ) {
501
511
return ;
@@ -545,6 +555,14 @@ export class NotebookMultiCursorController extends Disposable implements INotebo
545
555
return ; // should not happen
546
556
}
547
557
558
+ // Check if all matches are already covered by selections to avoid infinite looping
559
+ const totalSelections = this . trackedCells . reduce ( ( sum , trackedCell ) => sum + trackedCell . matchSelections . length , 0 ) ;
560
+
561
+ if ( totalSelections >= this . totalMatchesCount ) {
562
+ // All matches are already selected, make this a no-op like in regular editors
563
+ return ;
564
+ }
565
+
548
566
const findResult = notebookTextModel . findNextMatch (
549
567
this . word ,
550
568
{ cellIndex : index , position : focusedCell . getSelections ( ) [ focusedCell . getSelections ( ) . length - 1 ] . getEndPosition ( ) } ,
0 commit comments