@@ -18,13 +18,14 @@ import upArrow from '../images/up-arrow.svg?byContent';
18
18
import exitIcon from '../images/exit.svg?byContent' ;
19
19
20
20
function searchOverlay ( query , caseInsensitive ) {
21
- if ( typeof query == 'string' )
21
+ if ( typeof query == 'string' ) {
22
22
query = new RegExp (
23
23
query . replace ( / [ \- \[ \] \/ \{ \} \( \) \* \+ \? \. \\ \^ \$ \| ] / g, '\\$&' ) ,
24
24
caseInsensitive ? 'gi' : 'g'
25
25
) ;
26
- else if ( ! query . global )
26
+ } else if ( ! query . global ) {
27
27
query = new RegExp ( query . source , query . ignoreCase ? 'gi' : 'g' ) ;
28
+ }
28
29
29
30
return {
30
31
token : function ( stream ) {
@@ -49,6 +50,8 @@ function SearchState() {
49
50
this . caseInsensitive = true ;
50
51
this . wholeWord = false ;
51
52
this . replaceStarted = false ;
53
+ this . lastFileName =
54
+ document . querySelector ( '.editor__file-name span' ) ?. innerText || null ;
52
55
}
53
56
54
57
function getSearchState ( cm ) {
@@ -60,6 +63,50 @@ function getSearchCursor(cm, query, pos) {
60
63
return cm . getSearchCursor ( query , pos , getSearchState ( cm ) . caseInsensitive ) ;
61
64
}
62
65
66
+ function watchFileChanges ( cm , searchState , searchField ) {
67
+ let observer = null ;
68
+
69
+ function setupObserver ( ) {
70
+ var fileNameElement = document . querySelector ( '.editor__file-name span' ) ;
71
+
72
+ if ( ! fileNameElement ) {
73
+ setTimeout ( setupObserver , 500 ) ;
74
+ return ;
75
+ }
76
+
77
+ if ( observer ) {
78
+ return ;
79
+ }
80
+
81
+ observer = new MutationObserver ( ( ) => {
82
+ if ( searchField . value . length > 1 ) {
83
+ startSearch ( cm , searchState , searchField . value ) ;
84
+ }
85
+ } ) ;
86
+
87
+ observer . observe ( fileNameElement , { characterData : true , subtree : true } ) ;
88
+ }
89
+
90
+ function disconnectObserver ( ) {
91
+ if ( observer ) {
92
+ observer . disconnect ( ) ;
93
+ observer = null ;
94
+ }
95
+ }
96
+
97
+ setupObserver ( ) ;
98
+
99
+ setInterval ( ( ) => {
100
+ var searchDialog = document . querySelector ( '.CodeMirror-dialog' ) ;
101
+ if ( ! searchDialog && observer ) {
102
+ disconnectObserver ( ) ;
103
+ return ;
104
+ } else if ( searchDialog && ! observer ) {
105
+ setupObserver ( ) ;
106
+ }
107
+ } , 500 ) ;
108
+ }
109
+
63
110
function isMouseClick ( event ) {
64
111
if ( event . detail > 0 ) return true ;
65
112
else return false ;
@@ -88,10 +135,11 @@ function persistentDialog(cm, text, deflt, onEnter, replaceOpened, onKeyDown) {
88
135
89
136
var state = getSearchState ( cm ) ;
90
137
138
+ watchFileChanges ( cm , getSearchState ( cm ) , searchField ) ;
139
+
91
140
CodeMirror . on ( searchField , 'keyup' , function ( e ) {
92
141
state . replaceStarted = false ;
93
142
if ( e . keyCode !== 13 && searchField . value . length > 1 ) {
94
- // not enter and more than 1 character to search
95
143
startSearch ( cm , getSearchState ( cm ) , searchField . value ) ;
96
144
} else if ( searchField . value . length < 1 ) {
97
145
cm . display . wrapper . querySelector (
@@ -101,8 +149,8 @@ function persistentDialog(cm, text, deflt, onEnter, replaceOpened, onKeyDown) {
101
149
} ) ;
102
150
103
151
CodeMirror . on ( closeButton , 'click' , function ( ) {
104
- clearSearch ( cm ) ;
105
152
dialog . parentNode . removeChild ( dialog ) ;
153
+ clearSearch ( cm ) ;
106
154
cm . focus ( ) ;
107
155
} ) ;
108
156
@@ -323,7 +371,6 @@ function parseString(string) {
323
371
function parseQuery ( query , state ) {
324
372
var emptyQuery = 'x^' ; // matches nothing
325
373
if ( query === '' ) {
326
- // empty string matches nothing
327
374
query = emptyQuery ;
328
375
} else {
329
376
if ( state . regexp === false ) {
@@ -349,44 +396,64 @@ function parseQuery(query, state) {
349
396
}
350
397
351
398
function startSearch ( cm , state , query ) {
352
- state . queryText = query ;
353
- state . lastQuery = query ;
354
- state . query = parseQuery ( query , state ) ;
355
- cm . removeOverlay ( state . overlay , state . caseInsensitive ) ;
356
- state . overlay = searchOverlay ( state . query , state . caseInsensitive ) ;
357
- cm . addOverlay ( state . overlay ) ;
358
- if ( cm . showMatchesOnScrollbar ) {
359
- if ( state . annotate ) {
360
- state . annotate . clear ( ) ;
361
- state . annotate = null ;
399
+ var searchDialog = document . querySelector ( '.CodeMirror-dialog' ) ;
400
+ if ( searchDialog ) {
401
+ // check if the file has changed
402
+ let currentFileName = document . querySelector ( '.editor__file-name span' )
403
+ ?. innerText ;
404
+
405
+ if ( state . lastFileName !== currentFileName ) {
406
+ state . lastFileName = currentFileName ;
407
+ state . queryText = null ;
408
+ state . lastQuery = null ;
409
+ state . query = null ;
410
+ cm . removeOverlay ( state . overlay ) ;
411
+ state . overlay = null ;
412
+
413
+ if ( searchDialog ) {
414
+ cm . display . wrapper . querySelector (
415
+ '.CodeMirror-search-results'
416
+ ) . innerText = '0/0' ;
417
+ }
362
418
}
363
- state . annotate = cm . showMatchesOnScrollbar (
364
- state . query ,
365
- state . caseInsensitive
366
- ) ;
367
- }
368
419
369
- //Updating the UI everytime the search input changes
370
- var cursor = getSearchCursor ( cm , state . query ) ;
371
- cursor . findNext ( ) ;
372
- var num_match = cm . state . search . annotate . matches . length ;
373
- //no matches found
374
- if ( num_match == 0 ) {
375
- cm . display . wrapper . querySelector (
376
- '.CodeMirror-search-results'
377
- ) . innerText = i18n . t ( 'CodemirrorFindAndReplace.NoResults' ) ;
420
+ state . queryText = query ;
421
+ state . lastQuery = query ;
422
+ state . query = parseQuery ( query , state ) ;
378
423
cm . removeOverlay ( state . overlay , state . caseInsensitive ) ;
379
- } else {
380
- var next =
381
- cm . state . search . annotate . matches . findIndex ( ( s ) => {
382
- return (
383
- s . from . ch === cursor . from ( ) . ch && s . from . line === cursor . from ( ) . line
384
- ) ;
385
- } ) + 1 ;
386
- var text_match = next + '/' + num_match ;
387
- cm . display . wrapper . querySelector (
388
- '.CodeMirror-search-results'
389
- ) . innerText = text_match ;
424
+ state . overlay = searchOverlay ( state . query , state . caseInsensitive ) ;
425
+ cm . addOverlay ( state . overlay ) ;
426
+ if ( cm . showMatchesOnScrollbar ) {
427
+ if ( state . annotate ) {
428
+ state . annotate . clear ( ) ;
429
+ state . annotate = null ;
430
+ }
431
+ state . annotate = cm . showMatchesOnScrollbar (
432
+ state . query ,
433
+ state . caseInsensitive
434
+ ) ;
435
+ }
436
+
437
+ var cursor = getSearchCursor ( cm , state . query ) ;
438
+ cursor . findNext ( ) ;
439
+ var num_match = cm . state . search . annotate . matches . length ;
440
+ if ( num_match == 0 ) {
441
+ cm . display . wrapper . querySelector (
442
+ '.CodeMirror-search-results'
443
+ ) . innerText = i18n . t ( 'CodemirrorFindAndReplace.NoResults' ) ;
444
+ cm . removeOverlay ( state . overlay , state . caseInsensitive ) ;
445
+ } else {
446
+ var next =
447
+ cm . state . search . annotate . matches . findIndex ( ( s ) => {
448
+ return (
449
+ s . from . ch === cursor . from ( ) . ch && s . from . line === cursor . from ( ) . line
450
+ ) ;
451
+ } ) + 1 ;
452
+ var text_match = next + '/' + num_match ;
453
+ cm . display . wrapper . querySelector (
454
+ '.CodeMirror-search-results'
455
+ ) . innerText = text_match ;
456
+ }
390
457
}
391
458
}
392
459
0 commit comments