@@ -337,25 +337,59 @@ fn find_contiguous_candidates(
337337 return Vec :: new ( ) ;
338338 }
339339
340+ if ignore_empty_lines {
341+ return find_empty_line_tolerant_candidates ( lines, block, offset, & search_lines) ;
342+ }
343+
340344 let max_start = lines. len ( ) - search_lines. len ( ) ;
341345 ( offset..=max_start)
342- . filter_map ( |start| match_candidate ( lines, & search_lines, block, start, ignore_empty_lines) )
346+ . filter_map ( |start| {
347+ let end = start + search_lines. len ( ) ;
348+ let actual_lines: Vec < & String > = lines[ start..end] . iter ( ) . collect ( ) ;
349+ match_candidate ( lines, & actual_lines, & search_lines, block, start, end, false )
350+ } )
351+ . collect ( )
352+ }
353+
354+ fn find_empty_line_tolerant_candidates (
355+ lines : & [ String ] ,
356+ block : & SearchReplaceBlock ,
357+ offset : usize ,
358+ search_lines : & [ String ] ,
359+ ) -> Vec < MatchCandidate > {
360+ let compact_lines: Vec < ( usize , & String ) > =
361+ lines. iter ( ) . enumerate ( ) . skip ( offset) . filter ( |( _, line) | !line. trim ( ) . is_empty ( ) ) . collect ( ) ;
362+
363+ if compact_lines. len ( ) < search_lines. len ( ) {
364+ return Vec :: new ( ) ;
365+ }
366+
367+ let max_start = compact_lines. len ( ) - search_lines. len ( ) ;
368+ ( 0 ..=max_start)
369+ . filter_map ( |compact_start| {
370+ let compact_end = compact_start + search_lines. len ( ) ;
371+ let start = compact_lines[ compact_start] . 0 ;
372+ let end = compact_lines[ compact_end - 1 ] . 0 + 1 ;
373+ let actual_lines: Vec < & String > =
374+ compact_lines[ compact_start..compact_end] . iter ( ) . map ( |( _, line) | * line) . collect ( ) ;
375+ match_candidate ( lines, & actual_lines, search_lines, block, start, end, true )
376+ } )
343377 . collect ( )
344378}
345379
346380fn match_candidate (
347381 lines : & [ String ] ,
382+ actual_lines : & [ & String ] ,
348383 search_lines : & [ String ] ,
349384 block : & SearchReplaceBlock ,
350385 start : usize ,
386+ end : usize ,
351387 ignore_empty_lines : bool ,
352388) -> Option < MatchCandidate > {
353- let end = start + search_lines. len ( ) ;
354- let matched = & lines[ start..end] ;
355389 let mut tolerances = Vec :: new ( ) ;
356390 let mut score = 0 ;
357391
358- for ( actual, expected) in matched . iter ( ) . zip ( search_lines) {
392+ for ( actual, expected) in actual_lines . iter ( ) . zip ( search_lines) {
359393 let line_match = matching_tolerance ( actual, expected) ?;
360394 if let LineMatch :: Tolerated ( tolerance) = line_match {
361395 score += tolerance. score ( ) ;
@@ -374,6 +408,7 @@ fn match_candidate(
374408 replace = replace. into_iter ( ) . map ( |line| remove_leading_line_number ( & line) ) . collect ( ) ;
375409 }
376410 if tolerances. contains ( & ToleranceKind :: IgnoreIndentation ) {
411+ let matched = & lines[ start..end] ;
377412 replace = fix_indentation ( matched, search_lines, & replace) ;
378413 }
379414
0 commit comments