@@ -49,7 +49,7 @@ export default function(CodeMirror) {
49
49
else return false ;
50
50
}
51
51
52
- function persistentDialog ( cm , text , deflt , onEnter , onKeyDown ) {
52
+ function persistentDialog ( cm , text , deflt , onEnter , replaceOpened , onKeyDown ) {
53
53
var searchField = document . getElementsByClassName ( "CodeMirror-search-field" ) [ 0 ] ;
54
54
if ( ! searchField ) {
55
55
cm . openDialog ( text , onEnter , {
@@ -63,7 +63,7 @@ export default function(CodeMirror) {
63
63
closeOnBlur : false
64
64
} ) ;
65
65
66
- searchField = document . getElementsByClassName ( "CodeMirror-search -field") [ 0 ] ;
66
+ searchField = document . getElementById ( "Find-input -field") ;
67
67
68
68
var dialog = document . getElementsByClassName ( "CodeMirror-dialog" ) [ 0 ] ;
69
69
var closeButton = dialog . getElementsByClassName ( "close" ) [ 0 ] ;
@@ -141,6 +141,35 @@ export default function(CodeMirror) {
141
141
el . setAttribute ( 'aria-checked' , nextState ) ;
142
142
return nextState ;
143
143
}
144
+
145
+ var showReplaceButton = dialog . getElementsByClassName ( "CodeMirror-replace-button" ) [ 0 ] ;
146
+ var replaceDiv = dialog . getElementsByClassName ( "Replace-div" ) [ 0 ] ;
147
+ if ( replaceOpened ) {
148
+ replaceDiv . style . height = "138px" ;
149
+ }
150
+ CodeMirror . on ( showReplaceButton , "click" , function ( ) {
151
+ if ( replaceDiv . style . height === "0px" ) {
152
+ replaceDiv . style . height = "138px" ;
153
+ } else {
154
+ replaceDiv . style . height = "0px" ;
155
+ }
156
+ } ) ;
157
+
158
+ var replaceField = document . getElementById ( 'Replace-input-field' ) ;
159
+ CodeMirror . on ( replaceField , "keyup" , function ( e ) {
160
+ if ( e . keyCode == 13 ) // if enter
161
+ {
162
+ startSearch ( cm , getSearchState ( cm ) , searchField . value ) ;
163
+ replace ( cm , parseString ( searchField . value ) , parseString ( replaceField . value ) ) ;
164
+ }
165
+ } )
166
+
167
+ var doReplaceButton = document . getElementById ( 'Btn-replace' ) ;
168
+ CodeMirror . on ( doReplaceButton , "click" , function ( e ) {
169
+ startSearch ( cm , getSearchState ( cm ) , searchField . value ) ;
170
+ replace ( cm , parseString ( searchField . value ) , parseString ( replaceField . value ) ) ;
171
+ } )
172
+
144
173
} else {
145
174
searchField . focus ( ) ;
146
175
searchField . select ( ) ;
@@ -232,59 +261,6 @@ export default function(CodeMirror) {
232
261
return regexp ;
233
262
}
234
263
235
- var queryDialog = `
236
- <h3 class="CodeMirror-search-title">Find</h3>
237
- <input type="text" class="search-input CodeMirror-search-field" placeholder="Find in files" />
238
- <div class="CodeMirror-search-actions">
239
- <div class="CodeMirror-search-modifiers button-wrap">
240
- <button
241
- title="Regular expression"
242
- aria-label="Regular expression"
243
- role="checkbox"
244
- class="CodeMirror-search-modifier-button CodeMirror-regexp-button"
245
- >
246
- <span aria-hidden="true" class="button">.*</span>
247
- </button>
248
- <button
249
- title="Case sensitive"
250
- aria-label="Case sensitive"
251
- role="checkbox"
252
- class="CodeMirror-search-modifier-button CodeMirror-case-button"
253
- >
254
- <span aria-hidden="true" class="button">Aa</span>
255
- </button>
256
- <button
257
- title="Whole words"
258
- aria-label="Whole words"
259
- role="checkbox"
260
- class="CodeMirror-search-modifier-button CodeMirror-word-button"
261
- >
262
- <span aria-hidden="true" class="button">" "</span>
263
- </button>
264
- </div>
265
- <div class="CodeMirror-search-nav">
266
- <button class="CodeMirror-search-results"></button>
267
- <button
268
- title="Previous"
269
- aria-label="Previous"
270
- class="CodeMirror-search-button icon up-arrow prev"
271
- >
272
- </button>
273
- <button
274
- title="Next"
275
- aria-label="Next"
276
- class="CodeMirror-search-button icon down-arrow next"
277
- >
278
- </button>
279
- </div>
280
- </div>
281
- <button
282
- title="Close"
283
- aria-label="Close"
284
- class="CodeMirror-close-button close icon">
285
- </button>
286
- ` ;
287
-
288
264
function startSearch ( cm , state , originalQuery ) {
289
265
state . queryText = originalQuery ;
290
266
state . query = parseQuery ( originalQuery , state ) ;
@@ -301,6 +277,60 @@ export default function(CodeMirror) {
301
277
}
302
278
}
303
279
280
+ function doFindAndReplace ( cm , rev , persistent , immediate , ignoreQuery , replaceOpened ) {
281
+ var state = getSearchState ( cm ) ;
282
+ if ( ! ignoreQuery && state . query ) {
283
+ console . log ( 'Here' ) ;
284
+ return findNext ( cm , rev ) ;
285
+ }
286
+ var q = cm . getSelection ( ) || state . lastQuery ;
287
+ if ( persistent && cm . openDialog ) {
288
+ var hiding = null ;
289
+ var searchNext = function ( query , event ) {
290
+ CodeMirror . e_stop ( event ) ;
291
+ if ( ! query ) return ;
292
+ if ( query != state . queryText ) {
293
+ startSearch ( cm , state , query ) ;
294
+ state . posFrom = state . posTo = cm . getCursor ( ) ;
295
+ }
296
+ if ( hiding ) hiding . style . opacity = 1
297
+ findNext ( cm , event . shiftKey , function ( _ , to ) {
298
+ var dialog
299
+ if ( to . line < 3 && document . querySelector &&
300
+ ( dialog = cm . display . wrapper . querySelector ( ".CodeMirror-dialog" ) ) &&
301
+ dialog . getBoundingClientRect ( ) . bottom - 4 > cm . cursorCoords ( to , "window" ) . top )
302
+ ( hiding = dialog ) . style . opacity = 1
303
+ } )
304
+ } ;
305
+ persistentDialog ( cm , queryDialog , q , searchNext , replaceOpened , function ( event , query ) {
306
+ var keyName = CodeMirror . keyName ( event )
307
+ var cmd = CodeMirror . keyMap [ cm . getOption ( "keyMap" ) ] [ keyName ]
308
+ if ( ! cmd ) cmd = cm . getOption ( 'extraKeys' ) [ keyName ]
309
+ if ( cmd == "findNext" || cmd == "findPrev" ||
310
+ cmd == "findPersistentNext" || cmd == "findPersistentPrev" ) {
311
+ CodeMirror . e_stop ( event ) ;
312
+ startSearch ( cm , getSearchState ( cm ) , query ) ;
313
+ cm . execCommand ( cmd ) ;
314
+ } else if ( cmd == "find" || cmd == "findPersistent" ) {
315
+ CodeMirror . e_stop ( event ) ;
316
+ searchNext ( query , event ) ;
317
+ }
318
+ } ) ;
319
+ if ( immediate && q ) {
320
+ startSearch ( cm , state , q ) ;
321
+ findNext ( cm , rev ) ;
322
+ }
323
+ } else {
324
+ dialog ( cm , queryDialog , "Search for:" , q , function ( query ) {
325
+ if ( query && ! state . query ) cm . operation ( function ( ) {
326
+ startSearch ( cm , state , query ) ;
327
+ state . posFrom = state . posTo = cm . getCursor ( ) ;
328
+ findNext ( cm , rev ) ;
329
+ } ) ;
330
+ } ) ;
331
+ }
332
+ }
333
+
304
334
function doSearch ( cm , rev , persistent , immediate , ignoreQuery ) {
305
335
var state = getSearchState ( cm ) ;
306
336
if ( ! ignoreQuery && state . query ) return findNext ( cm , rev ) ;
@@ -382,12 +412,6 @@ export default function(CodeMirror) {
382
412
if ( state . annotate ) { state . annotate . clear ( ) ; state . annotate = null ; }
383
413
} ) ; }
384
414
385
- var replaceQueryDialog =
386
- '<input type="text" class="search-input CodeMirror-search-field"/><div class="close icon"></div>' ;
387
-
388
- var replacementQueryDialog = 'With: <input type="text" class="replace-input CodeMirror-search-field"/>' ;
389
- var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>" ;
390
-
391
415
function replaceAll ( cm , query , text ) {
392
416
cm . operation ( function ( ) {
393
417
for ( var cursor = getSearchCursor ( cm , query ) ; cursor . findNext ( ) ; ) {
@@ -399,60 +423,128 @@ export default function(CodeMirror) {
399
423
} ) ;
400
424
}
401
425
402
- // TODO: This will need updating if replace is implemented
403
- function replace ( cm , all ) {
426
+ function replace ( cm , queryText , withText , all ) {
427
+ if ( ! queryText ) return ;
404
428
const state = getSearchState ( cm ) ;
405
429
var prevDialog = document . getElementsByClassName ( "CodeMirror-dialog" ) [ 0 ] ;
406
430
if ( prevDialog ) {
407
431
clearSearch ( cm ) ;
408
- prevDialog . parentNode . removeChild ( prevDialog ) ;
409
- cm . focus ( ) ;
410
432
}
433
+ prevDialog . parentNode . removeChild ( prevDialog ) ;
434
+ cm . focus ( ) ;
411
435
if ( cm . getOption ( "readOnly" ) ) return ;
412
436
var query = cm . getSelection ( ) || state . lastQuery ;
413
- var dialogText = all ? "Replace all:" : "Replace:"
414
- dialog ( cm , dialogText + replaceQueryDialog , dialogText , query , function ( query ) {
415
- if ( ! query ) return ;
416
- query = parseQuery ( query , state ) ;
417
-
418
- dialog ( cm , replacementQueryDialog , "Replace with:" , "" , function ( text ) {
419
- text = parseString ( text )
420
- if ( all ) {
421
- replaceAll ( cm , query , text )
422
- } else {
423
- clearSearch ( cm ) ;
424
- var cursor = getSearchCursor ( cm , query , cm . getCursor ( "from" ) ) ;
425
- var advance = function ( ) {
426
- var start = cursor . from ( ) , match ;
427
- if ( ! ( match = cursor . findNext ( ) ) ) {
428
- cursor = getSearchCursor ( cm , query ) ;
429
- if ( ! ( match = cursor . findNext ( ) ) ||
430
- ( start && cursor . from ( ) . line == start . line && cursor . from ( ) . ch == start . ch ) ) return ;
431
- }
432
- cm . setSelection ( cursor . from ( ) , cursor . to ( ) ) ;
433
- cm . scrollIntoView ( { from : cursor . from ( ) , to : cursor . to ( ) } , 60 ) ;
434
- confirmDialog ( cm , doReplaceConfirm , "Replace?" ,
435
- [ function ( ) { doReplace ( match ) ; } , advance ,
436
- function ( ) { replaceAll ( cm , query , text ) } ] ) ;
437
- } ;
438
- var doReplace = function ( match ) {
439
- cursor . replace ( typeof query == "string" ? text :
440
- text . replace ( / \$ ( \d ) / g, function ( _ , i ) { return match [ i ] ; } ) ) ;
441
- advance ( ) ;
442
- } ;
443
- advance ( ) ;
437
+
438
+ if ( all ) {
439
+ replaceAll ( cm , query , withText )
440
+ } else {
441
+ clearSearch ( cm ) ;
442
+ var cursor = getSearchCursor ( cm , query , cm . getCursor ( "from" ) ) ;
443
+ var advance = function ( ) {
444
+ var start = cursor . from ( ) , match ;
445
+ if ( ! ( match = cursor . findNext ( ) ) ) {
446
+ cursor = getSearchCursor ( cm , query ) ;
447
+ if ( ! ( match = cursor . findNext ( ) ) ||
448
+ ( start && cursor . from ( ) . line == start . line && cursor . from ( ) . ch == start . ch ) ) return ;
444
449
}
445
- } ) ;
446
- } ) ;
450
+ cm . setSelection ( cursor . from ( ) , cursor . to ( ) ) ;
451
+ cm . scrollIntoView ( { from : cursor . from ( ) , to : cursor . to ( ) } , 60 ) ;
452
+ confirmDialog ( cm , doReplaceConfirm , "Replace?" ,
453
+ [ function ( ) { doReplace ( match ) ; } , advance ,
454
+ function ( ) { replaceAll ( cm , query , withText ) } ] ) ;
455
+ } ;
456
+ var doReplace = function ( match ) {
457
+ cursor . replace ( typeof query == "string" ? withText :
458
+ withText . replace ( / \$ ( \d ) / g, function ( _ , i ) { return match [ i ] ; } ) ) ;
459
+ advance ( ) ;
460
+ } ;
461
+ advance ( ) ;
462
+ }
447
463
}
448
464
449
- CodeMirror . commands . find = function ( cm ) { doSearch ( cm ) ; } ;
450
- CodeMirror . commands . findPersistent = function ( cm ) { doSearch ( cm , false , true , false , true ) ; } ;
451
- CodeMirror . commands . findPersistentNext = function ( cm ) { doSearch ( cm , false , true , true ) ; } ;
452
- CodeMirror . commands . findPersistentPrev = function ( cm ) { doSearch ( cm , true , true , true ) ; } ;
465
+ var doReplaceConfirm = "<button>Replace</button> <button>Skip</button> <button>Replace All</button> <button>Stop</button>" ;
466
+
467
+ var queryDialog = `
468
+ <h3 class="CodeMirror-search-title">Find</h3>
469
+ <input id="Find-input-field" type="text" class="search-input CodeMirror-search-field" placeholder="Find in files" />
470
+ <div class="CodeMirror-search-actions">
471
+ <div class="CodeMirror-search-modifiers button-wrap">
472
+ <button
473
+ title="Regular expression"
474
+ aria-label="Regular expression"
475
+ role="checkbox"
476
+ class="CodeMirror-search-modifier-button CodeMirror-regexp-button"
477
+ >
478
+ <span aria-hidden="true" class="button">.*</span>
479
+ </button>
480
+ <button
481
+ title="Case sensitive"
482
+ aria-label="Case sensitive"
483
+ role="checkbox"
484
+ class="CodeMirror-search-modifier-button CodeMirror-case-button"
485
+ >
486
+ <span aria-hidden="true" class="button">Aa</span>
487
+ </button>
488
+ <button
489
+ title="Whole words"
490
+ aria-label="Whole words"
491
+ role="checkbox"
492
+ class="CodeMirror-search-modifier-button CodeMirror-word-button"
493
+ >
494
+ <span aria-hidden="true" class="button">" "</span>
495
+ </button>
496
+ <button
497
+ title="Replace"
498
+ aria-label="Replace"
499
+ role="button"
500
+ class="CodeMirror-search-modifier-button CodeMirror-replace-button"
501
+ >
502
+ <span aria-hidden="true" class="button">Replace</span>
503
+ </button>
504
+ </div>
505
+ <div class="CodeMirror-search-nav">
506
+ <button class="CodeMirror-search-results"></button>
507
+ <button
508
+ title="Previous"
509
+ aria-label="Previous"
510
+ class="CodeMirror-search-button icon up-arrow prev"
511
+ >
512
+ </button>
513
+ <button
514
+ title="Next"
515
+ aria-label="Next"
516
+ class="CodeMirror-search-button icon down-arrow next"
517
+ >
518
+ </button>
519
+ </div>
520
+ </div>
521
+ <button
522
+ title="Close"
523
+ aria-label="Close"
524
+ class="CodeMirror-close-button close icon">
525
+ </button>
526
+ <div style="height: 0px; transition: 0.4s; overflow: hidden;" class="Replace-div">
527
+ <hr/>
528
+ <h3 class="CodeMirror-search-title">Replace</h3>
529
+ <input id="Replace-input-field" type="text" placeholder="Text to replace" class="search-input CodeMirror-search-field"/><div class="close icon"></div>
530
+ <button
531
+ title="Replace"
532
+ aria-label="Replace"
533
+ role="button"
534
+ id="Btn-replace"
535
+ class="CodeMirror-search-modifier-button CodeMirror-replace-button"
536
+ >
537
+ <span aria-hidden="true" class="button">Replace</span>
538
+ </button>
539
+ </div>
540
+ ` ;
541
+
542
+ CodeMirror . commands . findPersistent = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
543
+ CodeMirror . commands . findPersistentNext = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
544
+ CodeMirror . commands . findPersistentPrev = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
453
545
CodeMirror . commands . findNext = doSearch ;
454
546
CodeMirror . commands . findPrev = function ( cm ) { doSearch ( cm , true ) ; } ;
455
547
CodeMirror . commands . clearSearch = clearSearch ;
456
- CodeMirror . commands . replace = replace ;
457
- CodeMirror . commands . replaceAll = function ( cm ) { replace ( cm , true ) ; } ;
548
+ CodeMirror . commands . replace = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , true ) ; } ;
549
+ CodeMirror . commands . replaceAll = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , true ) ; } ;
458
550
} ;
0 commit comments