@@ -1000,23 +1000,35 @@ fn merge_text_and_snippet_edits(
10001000
10011001 let mut new_text = current_indel. insert ;
10021002
1003- // escape out snippet text
1004- stdx:: replace ( & mut new_text, '\\' , r"\\" ) ;
1005- stdx:: replace ( & mut new_text, '$' , r"\$" ) ;
1003+ // find which snippet bits need to be escaped
1004+ let escape_places =
1005+ new_text. rmatch_indices ( [ '\\' , '$' ] ) . map ( |( insert, _) | insert) . collect_vec ( ) ;
1006+ let mut escape_places = escape_places. into_iter ( ) . peekable ( ) ;
1007+ let mut escape_prior_bits = |new_text : & mut String , up_to : usize | {
1008+ for before in escape_places. peeking_take_while ( |insert| * insert >= up_to) {
1009+ new_text. insert ( before, '\\' ) ;
1010+ }
1011+ } ;
10061012
1007- // ... and apply!
1013+ // insert snippets, and escaping any needed bits along the way
10081014 for ( index, range) in all_snippets. iter ( ) . rev ( ) {
1009- let start = ( range. start ( ) - new_range. start ( ) ) . into ( ) ;
1010- let end = ( range . end ( ) - new_range . start ( ) ) . into ( ) ;
1015+ let text_range = range - new_range. start ( ) ;
1016+ let ( start , end) = ( text_range . start ( ) . into ( ) , text_range . end ( ) . into ( ) ) ;
10111017
10121018 if range. is_empty ( ) {
1019+ escape_prior_bits ( & mut new_text, start) ;
10131020 new_text. insert_str ( start, & format ! ( "${index}" ) ) ;
10141021 } else {
1022+ escape_prior_bits ( & mut new_text, end) ;
10151023 new_text. insert ( end, '}' ) ;
1024+ escape_prior_bits ( & mut new_text, start) ;
10161025 new_text. insert_str ( start, & format ! ( "${{{index}:" ) ) ;
10171026 }
10181027 }
10191028
1029+ // escape any remaining bits
1030+ escape_prior_bits ( & mut new_text, 0 ) ;
1031+
10201032 edits. push ( snippet_text_edit (
10211033 line_index,
10221034 true ,
0 commit comments