~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/Mono.Texteditor/Mono.TextEditor.Vi/ViActions.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
//
28
28
 
29
29
using System;
 
30
using System.Collections.Generic;
30
31
using System.Text;
31
32
 
32
33
namespace Mono.TextEditor.Vi
208
209
                {
209
210
                        data.Caret.Offset = data.FindCurrentWordStart (data.Caret.Offset);
210
211
                }
211
 
                
 
212
 
 
213
                public static void InnerWord (TextEditorData data)
 
214
                {
 
215
                        var start = data.FindCurrentWordStart (data.Caret.Offset);
 
216
                        var end = data.FindCurrentWordEnd (data.Caret.Offset);
 
217
                        data.SelectionRange = new TextSegment(start, end - start);
 
218
                }
 
219
 
 
220
                private static readonly Dictionary<char, char> EndToBeginCharMap = new Dictionary<char, char>
 
221
                {
 
222
                        {')', '('},
 
223
                        {'}', '{'},
 
224
                        {']', '['},
 
225
                        {'>', '<'},
 
226
                };
 
227
                private static readonly Dictionary<char, char> BeginToEndCharMap = new Dictionary<char, char>
 
228
                {
 
229
                        {'(', ')'},
 
230
                        {'{', '}'},
 
231
                        {'[', ']'},
 
232
                        {'<', '>'},
 
233
                };
 
234
 
 
235
                public static Action<TextEditorData> OuterSymbol (char command) 
 
236
                {
 
237
                        return data =>
 
238
                        {
 
239
                                SymbolBlock result;
 
240
                                if (!TryFindSymbolBlock (data, command, out result)) return;
 
241
 
 
242
                                data.SelectionRange = result.GetOuterTextSegment ();
 
243
                        };
 
244
                }
 
245
 
 
246
                public static Action<TextEditorData> InnerSymbol (char command) 
 
247
                {
 
248
                        return data =>
 
249
                        {
 
250
                                SymbolBlock result;
 
251
                                if (!TryFindSymbolBlock (data, command, out result)) return;
 
252
 
 
253
                                data.SelectionRange = result.GetInnerTextSegment ();
 
254
                        };
 
255
                }
 
256
 
 
257
                struct SymbolBlock
 
258
                {
 
259
                        public int StartOffset, EndOffset;
 
260
                        public DocumentLine StartLine, EndLine;
 
261
                        bool IsSameLine { get { return StartLine == EndLine; } }
 
262
 
 
263
                        public TextSegment GetInnerTextSegment()
 
264
                        {
 
265
                                var length = IsSameLine ? EndOffset - StartOffset : EndLine.PreviousLine.EndOffset - StartOffset;
 
266
                                return new TextSegment (StartOffset + 1, length - 1);
 
267
                        }
 
268
 
 
269
                        public TextSegment GetOuterTextSegment ()
 
270
                        {
 
271
                                return new TextSegment (StartOffset, (EndOffset - StartOffset) + 1);
 
272
                        }
 
273
                }
 
274
 
 
275
                static bool TryFindSymbolBlock (TextEditorData data, char command, out SymbolBlock result)
 
276
                {
 
277
                        char end, begin;
 
278
                        if (!BeginToEndCharMap.TryGetValue (command, out end)) end = command;
 
279
                        if (!EndToBeginCharMap.TryGetValue (command, out begin)) begin = command;
 
280
 
 
281
                        var offset = data.Caret.Offset;
 
282
 
 
283
                        var startTokenOffset = ParseForChar(data, offset, 0, end, begin, false);
 
284
                        var endTokenOffset = ParseForChar(data, offset, data.Length, begin, end, true);
 
285
 
 
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;
 
293
 
 
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;
 
299
 
 
300
                        if (!startTokenOffset.HasValue || !endTokenOffset.HasValue) throw new ViModeAbortException();
 
301
 
 
302
                        result = new SymbolBlock 
 
303
                        { 
 
304
                                StartOffset = startTokenOffset.GetValueOrDefault (),
 
305
                                EndOffset = endTokenOffset.GetValueOrDefault (),
 
306
                                StartLine = data.GetLineByOffset (startTokenOffset.GetValueOrDefault()),
 
307
                                EndLine = data.GetLineByOffset (endTokenOffset.GetValueOrDefault()),
 
308
                        };
 
309
                        return true;
 
310
                }
 
311
 
 
312
                static int? ParseForChar(TextEditorData data, int fromOffset, int toOffset, char oppositeToken, char findToken, bool forward)
 
313
                {
 
314
                        int increment = forward ? 1 : -1;
 
315
                        var symbolCount = 0;
 
316
                        for (int i = fromOffset; forward && i < toOffset || !forward && i >= toOffset; i += increment)
 
317
                        {
 
318
                                var c = data.GetCharAt(i);
 
319
                                if (c == oppositeToken) 
 
320
                                        symbolCount++;
 
321
                                else if (c == findToken)
 
322
                                {
 
323
                                        if (symbolCount == 0) return i;
 
324
                                        symbolCount--;
 
325
                                }
 
326
                        }
 
327
                        return null;
 
328
                }
 
329
 
 
330
                public static Action<TextEditorData> InnerQuote (char c)
 
331
                {
 
332
                        return data => 
 
333
                        {
 
334
                                int beginOffset, length;
 
335
                                if (TryFindInnerQuote (data, c, out beginOffset, out length))
 
336
                                        data.SelectionRange = new TextSegment (beginOffset, length);
 
337
                        };
 
338
                }
 
339
 
 
340
                static bool TryFindInnerQuote (TextEditorData data, char c, out int begin, out int length)
 
341
                {
 
342
                        begin = 0;
 
343
                        length = 0;
 
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;
 
348
 
 
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;
 
356
 
 
357
                        begin = beginOffset.GetValueOrDefault () + line.Offset + 1;
 
358
                        length = endOffset.GetValueOrDefault () - beginOffset.GetValueOrDefault () - 1;
 
359
                        return true;
 
360
                }
 
361
 
 
362
                public static Action<TextEditorData> OuterQuote (char c)
 
363
                {
 
364
                        return data => 
 
365
                        {
 
366
                                int beginOffset, length;
 
367
                                if (TryFindInnerQuote (data, c, out beginOffset, out length))
 
368
                                {
 
369
                                        beginOffset--;
 
370
                                        length += 2;
 
371
                                        data.SelectionRange = new TextSegment (beginOffset, length);
 
372
                                }
 
373
                        };
 
374
                }
 
375
 
 
376
                static int? ParseForQuote (string text, int start, char charToFind, bool forward) 
 
377
                {
 
378
                        int increment = forward ? 1 : -1;
 
379
                        for (int i = start; forward && i < text.Length || !forward && i >= 0; i += increment)
 
380
                        {
 
381
                                if (text[i] == charToFind &&
 
382
                                        (i < 1 || text[i-1] != '\\') &&
 
383
                                        (i < 2 || text[i-2] != '\\'))
 
384
                                        return i;
 
385
                        }
 
386
                        return null;
 
387
                }
 
388
 
212
389
                public static void LineEnd (TextEditorData data)
213
390
                {
214
391
                        int desiredColumn = System.Math.Max (data.Caret.Column, data.Caret.DesiredColumn);
239
416
                        return delegate (TextEditorData data) {
240
417
                                //get info about the old selection state
241
418
                                DocumentLocation oldCaret = data.Caret.Location, oldAnchor = oldCaret, oldLead = oldCaret;
242
 
                                if (data.MainSelection != null) {
 
419
                                if (data.IsSomethingSelected) {
243
420
                                        oldLead = data.MainSelection.Lead;
244
421
                                        oldAnchor = data.MainSelection.Anchor;
245
422
                                }
250
427
                                SelectionActions.EndSelection (data);
251
428
                                
252
429
                                DocumentLocation newCaret = data.Caret.Location, newAnchor = newCaret, newLead = newCaret;
253
 
                                if (data.MainSelection != null) {
 
430
                                if (data.IsSomethingSelected) {
254
431
                                        newLead = data.MainSelection.Lead;
255
432
                                        newAnchor = data.MainSelection.Anchor;
256
433
                                }