209
210
data.Caret.Offset = data.FindCurrentWordStart (data.Caret.Offset);
213
public static void InnerWord (TextEditorData data)
215
var start = data.FindCurrentWordStart (data.Caret.Offset);
216
var end = data.FindCurrentWordEnd (data.Caret.Offset);
217
data.SelectionRange = new TextSegment(start, end - start);
220
private static readonly Dictionary<char, char> EndToBeginCharMap = new Dictionary<char, char>
227
private static readonly Dictionary<char, char> BeginToEndCharMap = new Dictionary<char, char>
235
public static Action<TextEditorData> OuterSymbol (char command)
240
if (!TryFindSymbolBlock (data, command, out result)) return;
242
data.SelectionRange = result.GetOuterTextSegment ();
246
public static Action<TextEditorData> InnerSymbol (char command)
251
if (!TryFindSymbolBlock (data, command, out result)) return;
253
data.SelectionRange = result.GetInnerTextSegment ();
259
public int StartOffset, EndOffset;
260
public DocumentLine StartLine, EndLine;
261
bool IsSameLine { get { return StartLine == EndLine; } }
263
public TextSegment GetInnerTextSegment()
265
var length = IsSameLine ? EndOffset - StartOffset : EndLine.PreviousLine.EndOffset - StartOffset;
266
return new TextSegment (StartOffset + 1, length - 1);
269
public TextSegment GetOuterTextSegment ()
271
return new TextSegment (StartOffset, (EndOffset - StartOffset) + 1);
275
static bool TryFindSymbolBlock (TextEditorData data, char command, out SymbolBlock result)
278
if (!BeginToEndCharMap.TryGetValue (command, out end)) end = command;
279
if (!EndToBeginCharMap.TryGetValue (command, out begin)) begin = command;
281
var offset = data.Caret.Offset;
283
var startTokenOffset = ParseForChar(data, offset, 0, end, begin, false);
284
var endTokenOffset = ParseForChar(data, offset, data.Length, begin, end, true);
286
// Use the editor's FindMatchingBrace built-in functionality. It's better at handling erroneous braces
287
// inside quotes. We still need to do the above paragraph because we needed to find the braces.
288
var matchingStartBrace = endTokenOffset.HasValue ? data.Document.GetMatchingBracketOffset(
289
endTokenOffset.GetValueOrDefault ()) : -1;
290
if (matchingStartBrace >= 0 && (!startTokenOffset.HasValue
291
|| matchingStartBrace != startTokenOffset.GetValueOrDefault ()))
292
startTokenOffset = matchingStartBrace;
294
var matchingEndBrace = startTokenOffset.HasValue && data.GetCharAt (offset) != end ?
295
data.Document.GetMatchingBracketOffset(startTokenOffset.GetValueOrDefault ()) : -1;
296
if (matchingEndBrace >= 0 && (!endTokenOffset.HasValue
297
|| matchingEndBrace != endTokenOffset.GetValueOrDefault ()))
298
endTokenOffset = matchingEndBrace;
300
if (!startTokenOffset.HasValue || !endTokenOffset.HasValue) throw new ViModeAbortException();
302
result = new SymbolBlock
304
StartOffset = startTokenOffset.GetValueOrDefault (),
305
EndOffset = endTokenOffset.GetValueOrDefault (),
306
StartLine = data.GetLineByOffset (startTokenOffset.GetValueOrDefault()),
307
EndLine = data.GetLineByOffset (endTokenOffset.GetValueOrDefault()),
312
static int? ParseForChar(TextEditorData data, int fromOffset, int toOffset, char oppositeToken, char findToken, bool forward)
314
int increment = forward ? 1 : -1;
316
for (int i = fromOffset; forward && i < toOffset || !forward && i >= toOffset; i += increment)
318
var c = data.GetCharAt(i);
319
if (c == oppositeToken)
321
else if (c == findToken)
323
if (symbolCount == 0) return i;
330
public static Action<TextEditorData> InnerQuote (char c)
334
int beginOffset, length;
335
if (TryFindInnerQuote (data, c, out beginOffset, out length))
336
data.SelectionRange = new TextSegment (beginOffset, length);
340
static bool TryFindInnerQuote (TextEditorData data, char c, out int begin, out int length)
344
var currentOffset = data.Caret.Offset;
345
var lineText = data.Document.GetLineText (data.Caret.Line);
346
var line = data.Document.GetLine (data.Caret.Line);
347
var lineOffset = currentOffset - line.Offset;
349
var beginOffset = ParseForQuote (lineText, lineOffset - 1, c, false);
350
if (!beginOffset.HasValue && lineText[lineOffset] == c)
351
beginOffset = lineOffset;
352
if (!beginOffset.HasValue) return false;
353
var startEndSearchAt = beginOffset.GetValueOrDefault () == lineOffset ? lineOffset + 1 : lineOffset;
354
var endOffset = ParseForQuote (lineText, startEndSearchAt, c, true);
355
if (!endOffset.HasValue) return false;
357
begin = beginOffset.GetValueOrDefault () + line.Offset + 1;
358
length = endOffset.GetValueOrDefault () - beginOffset.GetValueOrDefault () - 1;
362
public static Action<TextEditorData> OuterQuote (char c)
366
int beginOffset, length;
367
if (TryFindInnerQuote (data, c, out beginOffset, out length))
371
data.SelectionRange = new TextSegment (beginOffset, length);
376
static int? ParseForQuote (string text, int start, char charToFind, bool forward)
378
int increment = forward ? 1 : -1;
379
for (int i = start; forward && i < text.Length || !forward && i >= 0; i += increment)
381
if (text[i] == charToFind &&
382
(i < 1 || text[i-1] != '\\') &&
383
(i < 2 || text[i-2] != '\\'))
212
389
public static void LineEnd (TextEditorData data)
214
391
int desiredColumn = System.Math.Max (data.Caret.Column, data.Caret.DesiredColumn);