@@ -166,7 +166,7 @@ private CodeString DeleteMatchingTokensMultiline(SelfClosingPair pair, CodeStrin
166
166
var closingLine = lines [ closingTokenPosition . EndLine ] . Remove ( closingTokenPosition . StartColumn , 1 ) ;
167
167
lines [ closingTokenPosition . EndLine ] = closingLine ;
168
168
169
- if ( closingLine == pair . OpeningChar . ToString ( ) )
169
+ if ( closingLine == pair . OpeningChar . ToString ( ) || closingLine == pair . OpeningChar + " _" || closingLine == pair . OpeningChar + " & _" )
170
170
{
171
171
lines [ closingTokenPosition . EndLine ] = string . Empty ;
172
172
}
@@ -184,78 +184,94 @@ private CodeString DeleteMatchingTokensMultiline(SelfClosingPair pair, CodeStrin
184
184
lines = lines . Where ( ( x , i ) => i <= position . StartLine || ! string . IsNullOrWhiteSpace ( x ) ) . ToArray ( ) ;
185
185
lastLine = lines [ lines . Length - 1 ] ;
186
186
187
- if ( lastLine . EndsWith ( " _" ) )
187
+ if ( lastLine . EndsWith ( " _" ) && finalCaretPosition . StartLine == lines . Length - 1 )
188
188
{
189
- // we can't leave the logical line ending with a line continuation token.
190
- if ( lastLine . EndsWith ( " & vbNewLine & _" ) )
191
- {
192
- // assume " & vbNewLine & _" was added by smart-concat?
193
- lines [ lines . Length - 1 ] = lastLine . Substring ( 0 ,
194
- lastLine . Length - " & vbNewLine & _" . Length ) ;
195
- }
196
- else
197
- {
198
- lines [ lines . Length - 1 ] = lastLine . TrimEnd ( ' ' , '_' ) ;
199
- }
189
+ finalCaretPosition = HandleBackspaceContinuations ( lines , finalCaretPosition ) ;
200
190
}
191
+ }
192
+
193
+ var caretLine = lines [ finalCaretPosition . StartLine ] ;
194
+ if ( caretLine . EndsWith ( " _" ) && finalCaretPosition . StartLine == lines . Length - 1 )
195
+ {
196
+ finalCaretPosition = HandleBackspaceContinuations ( lines , finalCaretPosition ) ;
197
+ }
198
+ else if ( caretLine . EndsWith ( "& _" ) || caretLine . EndsWith ( "& _" ) )
199
+ {
200
+ HandleBackspaceContinuations ( lines , finalCaretPosition ) ;
201
+ }
201
202
202
- var nonEmptyLines = lines
203
- . Where ( x => ! string . IsNullOrWhiteSpace ( x ) )
204
- . ToArray ( ) ;
205
- var lastNonEmptyLine = nonEmptyLines . Length > 0 ? nonEmptyLines [ nonEmptyLines . Length - 1 ] : null ;
206
- if ( lastNonEmptyLine != null )
203
+ var nonEmptyLines = lines . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) . ToArray ( ) ;
204
+ var lastNonEmptyLine = nonEmptyLines . Length > 0 ? nonEmptyLines [ nonEmptyLines . Length - 1 ] : null ;
205
+ if ( lastNonEmptyLine != null )
206
+ {
207
+ if ( position . StartLine > nonEmptyLines . Length - 1 )
207
208
{
208
- if ( position . StartLine > nonEmptyLines . Length - 1 )
209
- {
210
- // caret is on a now-empty line, shift one line up.
211
- finalCaretPosition = new Selection ( position . StartLine - 1 , lastNonEmptyLine . Length - 1 ) ;
212
- }
209
+ // caret is on a now-empty line, shift one line up.
210
+ finalCaretPosition = new Selection ( position . StartLine - 1 , lastNonEmptyLine . Length - 1 ) ;
211
+ }
213
212
214
- if ( lastNonEmptyLine . EndsWith ( " _" ) )
213
+ if ( lastNonEmptyLine . EndsWith ( " _" ) )
214
+ {
215
+ var newPosition = HandleBackspaceContinuations ( nonEmptyLines , new Selection ( nonEmptyLines . Length - 1 , 1 ) ) ;
216
+ if ( finalCaretPosition . StartLine == nonEmptyLines . Length - 1 )
215
217
{
216
- nonEmptyLines [ nonEmptyLines . Length - 1 ] = lastNonEmptyLine . Remove ( lastNonEmptyLine . Length - 2 ) ;
217
- lastNonEmptyLine = nonEmptyLines [ nonEmptyLines . Length - 1 ] ;
218
-
219
- if ( lastNonEmptyLine . EndsWith ( "&" ) )
220
- {
221
- // we're not concatenating anything anymore; remove concat operator too.
222
- var concatOffset = lastNonEmptyLine . EndsWith ( " &" ) ? 2 : 1 ;
223
- nonEmptyLines [ nonEmptyLines . Length - 1 ] = lastNonEmptyLine . Remove ( lastNonEmptyLine . Length - concatOffset ) ;
224
- TrimLastNonEmptyLine ( nonEmptyLines , "& vbNewLine" ) ;
225
- TrimLastNonEmptyLine ( nonEmptyLines , "& vbCrLf" ) ;
226
- TrimLastNonEmptyLine ( nonEmptyLines , "& vbCr" ) ;
227
- TrimLastNonEmptyLine ( nonEmptyLines , "& vbLf" ) ;
228
- }
229
-
230
- // we're keeping the closing quote, but let's put the caret inside:
231
- lastNonEmptyLine = nonEmptyLines [ nonEmptyLines . Length - 1 ] ;
232
- var quoteOffset = lastNonEmptyLine . EndsWith ( "\" " ) ? 1 : 0 ;
233
- finalCaretPosition = new Selection (
234
- finalCaretPosition . StartLine ,
235
- lastNonEmptyLine . Length - quoteOffset ) ;
218
+ finalCaretPosition = newPosition ;
236
219
}
237
-
238
- lines = nonEmptyLines ;
239
220
}
221
+
222
+ lines = nonEmptyLines ;
240
223
}
241
224
225
+
242
226
// remove any dangling empty lines...
243
- // lines = lines.Where((x, i) => i <= position.StartLine || !string.IsNullOrWhiteSpace(x)).ToArray();
227
+ lines = lines . Where ( ( x , i ) => i <= position . StartLine || ! string . IsNullOrWhiteSpace ( x ) ) . ToArray ( ) ;
244
228
245
229
return new CodeString ( string . Join ( "\r \n " , lines ) , finalCaretPosition ,
246
230
new Selection ( original . SnippetPosition . StartLine , 1 , original . SnippetPosition . EndLine , 1 ) ) ;
231
+ }
232
+
233
+ private static Selection HandleBackspaceContinuations ( string [ ] nonEmptyLines , Selection finalCaretPosition )
234
+ {
235
+ var lineIndex = Math . Min ( finalCaretPosition . StartLine , nonEmptyLines . Length - 1 ) ;
236
+ var line = nonEmptyLines [ lineIndex ] ;
237
+ if ( line . EndsWith ( " _" ) && lineIndex == nonEmptyLines . Length - 1 )
238
+ {
239
+ nonEmptyLines [ lineIndex ] = line . Remove ( line . Length - 2 ) ;
240
+ line = nonEmptyLines [ lineIndex ] ;
241
+ }
247
242
243
+ if ( lineIndex == nonEmptyLines . Length - 1 )
244
+ {
245
+ line = nonEmptyLines [ lineIndex ] ;
246
+ }
247
+
248
+ if ( line . EndsWith ( "&" ) )
249
+ {
250
+ // we're not concatenating anything anymore; remove concat operator too.
251
+ var concatOffset = line . EndsWith ( " &" ) ? 2 : 1 ;
252
+ nonEmptyLines [ lineIndex ] = line . Remove ( line . Length - concatOffset ) ;
253
+ }
254
+ TrimNonEmptyLine ( nonEmptyLines , lineIndex , "& vbNewLine" ) ;
255
+ TrimNonEmptyLine ( nonEmptyLines , lineIndex , "& vbCrLf" ) ;
256
+ TrimNonEmptyLine ( nonEmptyLines , lineIndex , "& vbCr" ) ;
257
+ TrimNonEmptyLine ( nonEmptyLines , lineIndex , "& vbLf" ) ;
258
+
259
+ // we're keeping the closing quote, but let's put the caret inside:
260
+ line = nonEmptyLines [ lineIndex ] ;
261
+ var quoteOffset = line . EndsWith ( "\" " ) ? 1 : 0 ;
262
+ finalCaretPosition = new Selection ( finalCaretPosition . StartLine , line . Length - quoteOffset ) ;
263
+ return finalCaretPosition ;
248
264
}
249
265
250
- private static void TrimLastNonEmptyLine ( string [ ] nonEmptyLines , string ending )
266
+ private static void TrimNonEmptyLine ( string [ ] nonEmptyLines , int lineIndex , string ending )
251
267
{
252
- var lastNonEmptyLine = nonEmptyLines [ nonEmptyLines . Length - 1 ] ;
253
- if ( lastNonEmptyLine . EndsWith ( ending , StringComparison . OrdinalIgnoreCase ) )
268
+ var line = nonEmptyLines [ lineIndex ] ;
269
+ if ( line . EndsWith ( ending , StringComparison . OrdinalIgnoreCase ) )
254
270
{
255
- var offset = lastNonEmptyLine . EndsWith ( " " + ending , StringComparison . OrdinalIgnoreCase )
271
+ var offset = line . EndsWith ( " " + ending , StringComparison . OrdinalIgnoreCase )
256
272
? ending . Length + 1
257
273
: ending . Length ;
258
- nonEmptyLines [ nonEmptyLines . Length - 1 ] = lastNonEmptyLine . Remove ( lastNonEmptyLine . Length - offset ) ;
274
+ nonEmptyLines [ lineIndex ] = line . Remove ( line . Length - offset ) ;
259
275
}
260
276
}
261
277
0 commit comments