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

« back to all changes in this revision

Viewing changes to src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxMode.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:
28
28
using System;
29
29
using System.Linq;
30
30
using System.Collections.Generic;
31
 
using System.Collections.ObjectModel;
32
31
using System.Text;
33
32
using System.Xml;
34
 
using System.Diagnostics;
 
33
using System.IO;
35
34
 
36
35
namespace Mono.TextEditor.Highlighting
37
36
{
63
62
                {
64
63
                        if (doc == null || doc.SuppressHighlightUpdate)
65
64
                                return;
66
 
                        Mono.TextEditor.Highlighting.SyntaxModeService.StartUpdate (doc, this, e.Offset, e.Offset + e.InsertionLength);
 
65
                        SyntaxModeService.StartUpdate (doc, this, e.Offset, e.Offset + e.InsertionLength);
67
66
                }
68
67
 
69
68
                void HandleTextSet (object sender, EventArgs e)
70
69
                {
71
70
                        if (doc == null || doc.SuppressHighlightUpdate)
72
71
                                return;
73
 
                        Mono.TextEditor.Highlighting.SyntaxModeService.StartUpdate (doc, this, 0, doc.TextLength);
 
72
                        SyntaxModeService.StartUpdate (doc, this, 0, doc.TextLength);
74
73
                }
75
74
                
76
75
                public event EventHandler DocumentSet;
77
76
                
78
77
                protected virtual void OnDocumentSet (EventArgs e)
79
78
                {
80
 
                        EventHandler handler = this.DocumentSet;
 
79
                        var handler = DocumentSet;
81
80
                        if (handler != null)
82
81
                                handler (this, e);
83
82
                }       
98
97
                
99
98
                protected SyntaxMode () : base (null)
100
99
                {
101
 
                        DefaultColor = "text";
 
100
                        DefaultColor = "Plain Text";
102
101
                        Name = "<root>";
103
102
                        this.Delimiter = "&()<>{}[]~!%^*-+=|\\#/:;\"' ,\t.?";
104
103
                }
133
132
                        }
134
133
                        if (result != null) {
135
134
                                // crop to begin
136
 
                                if (result.Offset != offset) {
137
 
                                        while (result != null && result.EndOffset < offset)
 
135
                                if (result.Offset < offset) {
 
136
                                        while (result != null && result.EndOffset < offset) {
138
137
                                                result = result.Next;
 
138
                                        }
139
139
                                        if (result != null) {
140
140
                                                int endOffset = result.EndOffset;
141
141
                                                result.Offset = offset;
142
142
                                                result.Length = endOffset - offset;
143
143
                                        }
144
144
                                }
145
 
 
146
 
                                if (result != null && offset + length != chunkParser.lineOffset + line.Length) {
147
 
                                        // crop to end
148
 
                                        Chunk cur = result;
149
 
                                        while (cur != null && cur.EndOffset < offset + length) {
150
 
                                                cur = cur.Next;
151
 
                                        }
152
 
                                        if (cur != null) {
153
 
                                                cur.Length = offset + length - cur.Offset;
154
 
                                                cur.Next = null;
155
 
                                        }
156
 
                                }
157
145
                        }
158
146
                        while (result != null) {
 
147
                                // crop to end
 
148
                                if (result.EndOffset >= offset + length) {
 
149
                                        result.Length = offset + length - result.Offset;
 
150
                                        result.Next = null;
 
151
                                        if (result.Length < 0) {
 
152
                                                result.Length = 0;
 
153
                                                yield break;
 
154
                                        }
 
155
                                }
159
156
                                yield return result;
160
157
                                result = result.Next;
161
158
                        }
165
162
                {
166
163
                        return string.Format ("#{0:X2}{1:X2}{2:X2}", color.Red >> 8, color.Green >> 8, color.Blue >> 8);
167
164
                }
 
165
                public static string ColorToPangoMarkup (Cairo.Color color)
 
166
                {
 
167
                        return ColorToPangoMarkup ((Gdk.Color)((HslColor)color));
 
168
                }
168
169
 
169
170
                public static int GetIndentLength (TextDocument doc, int offset, int length, bool skipFirstLine)
170
171
                {
215
216
                                        return spanStack;
216
217
                                }
217
218
                                set {
218
 
                                        this.spanStack = value;
 
219
                                        spanStack = value;
219
220
                                }
220
221
                        }
221
222
 
224
225
                                        return ruleStack;
225
226
                                }
226
227
                                set {
227
 
                                        this.ruleStack = value;
228
 
                                        this.CurRule = ruleStack.Peek ();
 
228
                                        ruleStack = value;
 
229
                                        CurRule = ruleStack.Peek ();
229
230
                                }
230
231
                        }
231
232
 
236
237
                                        return result;
237
238
                                Rule rule = mode;
238
239
                                result.Push (mode);
239
 
                                foreach (Span span in this.spanStack.Reverse ()) {
240
 
                                        Rule tmp = rule.GetRule (doc, span.Rule) ?? this.CurRule;
 
240
                                foreach (Span span in spanStack.Reverse ()) {
 
241
                                        Rule tmp = rule.GetRule (doc, span.Rule) ?? CurRule;
241
242
                                        result.Push (tmp);
242
243
                                        rule = tmp;
243
244
                                }
275
276
                        {
276
277
                                spanStack.Push (span);
277
278
                                ruleStack.Push (rule);
278
 
                                this.CurRule = rule;
279
 
                                this.CurSpan = span;
 
279
                                CurRule = rule;
 
280
                                CurSpan = span;
280
281
                        }
281
282
 
282
283
                        public Span PopSpan ()
287
288
                                }
288
289
                                if (ruleStack.Count > 1)
289
290
                                        ruleStack.Pop ();
290
 
                                this.CurRule = ruleStack.Peek ();
291
 
                                this.CurSpan = spanStack.Count > 0 ? spanStack.Peek () : null;
 
291
                                CurRule = ruleStack.Peek ();
 
292
                                CurSpan = spanStack.Count > 0 ? spanStack.Peek () : null;
292
293
                                return result;
293
294
                        }
294
295
 
321
322
                        }
322
323
                
323
324
                                                
324
 
                        protected virtual void ScanSpan (ref int i)
 
325
                        protected virtual bool ScanSpan (ref int i)
325
326
                        {
326
327
                                int textOffset = i - StartOffset;
327
328
                                for (int j = 0; j < CurRule.Spans.Length; j++) {
336
337
                                        } 
337
338
 
338
339
                                        RegexMatch match = span.Begin.TryMatch (CurText, textOffset);
339
 
                                        if (!match.Success)
 
340
                                        if (!match.Success) {
340
341
                                                continue;
 
342
                                        }
341
343
                                        // scan for span exit which cancels the span.
342
344
                                        if ((span.ExitFlags & SpanExitFlags.CancelSpan) == SpanExitFlags.CancelSpan && span.Exit != null) {
343
345
                                                bool foundEnd = false;
344
346
                                                for (int k = i + match.Length; k < CurText.Length; k++) {
345
347
                                                        if (span.Exit.TryMatch (CurText, k - StartOffset).Success)
346
 
                                                                return;
 
348
                                                                return false;
347
349
                                                        if (span.End.TryMatch (CurText, k - StartOffset).Success) {
348
350
                                                                foundEnd = true;
349
351
                                                                break;
350
352
                                                        }
351
353
                                                }
352
354
                                                if (!foundEnd)
353
 
                                                        return;
 
355
                                                        return false;
354
356
                                        }
355
357
                                        
356
358
                                        bool mismatch = false;
359
361
                                        if (mismatch)
360
362
                                                continue;
361
363
                                        FoundSpanBegin (span, i, match.Length);
362
 
                                        i += match.Length - 1;
363
 
                                        return;
 
364
                                        i += System.Math.Max (0, match.Length - 1);
 
365
                                        return true;
364
366
                                }
 
367
                                return false;
365
368
                        }
366
369
 
367
370
                        protected virtual bool ScanSpanEnd (Span cur, ref int i)
372
375
                                        RegexMatch match = cur.End.TryMatch (CurText, textOffset);
373
376
                                        if (match.Success) {
374
377
                                                FoundSpanEnd (cur, i, match.Length);
375
 
                                                i += match.Length - 1;
 
378
                                                i += System.Math.Max (0, match.Length - 1);
376
379
                                                return true;
377
380
                                        }
378
381
                                }
381
384
                                        RegexMatch match = cur.Exit.TryMatch (CurText, textOffset);
382
385
                                        if (match.Success) {
383
386
                                                FoundSpanExit (cur, i, match.Length);
384
 
                                                i += match.Length - 1;
 
387
                                                i += System.Math.Max (0, match.Length - 1);
385
388
                                                return true;
386
389
                                        }
387
390
                                }
417
420
                                                                }
418
421
                                                        }
419
422
                                                        if (!mismatch) {
420
 
                                                                i += cur.Escape.Length;
421
 
                                                                if (cur.Escape.Length > 1)
422
 
                                                                        i--;
 
423
                                                                int j = i + cur.Escape.Length - 1;
 
424
                                                                ParseChar (ref i, CurText [textIndex]);
 
425
                                                                i = j;
423
426
                                                                continue;
424
427
                                                        }
425
428
                                                }
426
429
                                                if (ScanSpanEnd (cur, ref i))
427
430
                                                        continue;
428
 
                                        }
429
 
                                        ScanSpan (ref i);
430
 
                                        if (i < doc.TextLength)
431
 
                                                ParseChar (ref i, CurText [textIndex]);
 
431
 
 
432
                                        }
 
433
                                        if (!ScanSpan (ref i)) {
 
434
                                                if (i < doc.TextLength)
 
435
                                                        ParseChar (ref i, CurText [textIndex]);
 
436
                                        }
432
437
                                }
433
438
                        }
434
439
                }
435
440
 
436
441
                public class ChunkParser
437
442
                {
438
 
                        readonly string defaultStyle = "text";
 
443
                        readonly string defaultStyle = "Plain Text";
439
444
                        protected SpanParser spanParser;
440
445
                        protected TextDocument doc;
441
446
                        protected DocumentLine line;
457
462
                                        throw new ArgumentNullException ("line");
458
463
                        }
459
464
 
460
 
                        Chunk startChunk = null;
 
465
                        Chunk startChunk;
461
466
                        Chunk endChunk;
462
467
 
463
468
                        protected virtual void AddRealChunk (Chunk chunk)
517
522
                                        return result;
518
523
                                }
519
524
                                string rule = spanParser.SpanStack.Peek ().Rule;
520
 
                                if (!string.IsNullOrEmpty (rule) && rule.StartsWith ("mode:"))
 
525
                                if (!string.IsNullOrEmpty (rule) && rule.StartsWith ("mode:", StringComparison.Ordinal))
521
526
                                        return spanParser.CurRule.DefaultColor ?? defaultStyle;
522
527
                                return spanParser.SpanStack.Peek ().Color;
523
528
                        }
555
560
                                curChunk.SpanStack.Push (span);
556
561
                                AddChunk (ref curChunk, 0, curChunk.Style);
557
562
                                foreach (SemanticRule semanticRule in spanRule.SemanticRules) {
558
 
                                        semanticRule.Analyze (this.doc, line, curChunk, offset, line.EndOffsetIncludingDelimiter);
 
563
                                        semanticRule.Analyze (doc, line, curChunk, offset, line.EndOffsetIncludingDelimiter);
559
564
                                }
560
565
                        }
561
566
 
580
585
                                spanParser.PopSpan ();
581
586
                        }
582
587
                        protected StringBuilder wordbuilder = new StringBuilder ();
583
 
                        bool inWord = false;
 
588
                        bool inWord;
584
589
                        public void ParseChar (ref int i, char ch)
585
590
                        {
586
 
                                int textOffset = i - spanParser.StartOffset;
587
 
 
588
591
                                Rule cur = spanParser.CurRule;
589
592
                                bool isWordPart = cur.Delimiter.IndexOf (ch) < 0;
590
 
 
591
593
                                if (inWord && !isWordPart || !inWord && isWordPart)
592
594
                                        AddChunk (ref curChunk, 0, curChunk.Style = GetStyle (curChunk) ?? GetSpanStyle ());
593
595
 
594
596
                                inWord = isWordPart;
595
597
 
596
 
                                if (cur.HasMatches && i - curChunk.Offset == 0) {
 
598
                                if (cur.HasMatches && (i - curChunk.Offset == 0 || string.IsNullOrEmpty (cur.Delimiter))) {
597
599
                                        Match foundMatch = null;
598
 
                                        int   foundMatchLength = 0;
 
600
                                        var   foundMatchLength = new int[0];
 
601
                                        int textOffset = i - spanParser.StartOffset;
599
602
                                        foreach (Match ruleMatch in cur.Matches) {
600
 
                                                int matchLength = ruleMatch.TryMatch (spanParser.CurText, textOffset);
601
 
                                                if (foundMatchLength < matchLength) {
 
603
                                                var matchLength = ruleMatch.TryMatch (spanParser.CurText, textOffset);
 
604
                                                if (foundMatchLength.Length < matchLength.Length) {
602
605
                                                        foundMatch = ruleMatch;
603
606
                                                        foundMatchLength = matchLength;
604
607
                                                }
605
608
                                        }
606
609
                                        if (foundMatch != null) {
607
 
                                                AddChunk (ref curChunk, foundMatchLength, GetChunkStyleColor (foundMatch.Color));
608
 
                                                i += foundMatchLength - 1;
609
 
                                                curChunk.Length = i - curChunk.Offset + 1;
610
 
                                                return;
 
610
                                                if (foundMatch.IsGroupMatch) {
 
611
                                                        for (int j = 1; j < foundMatchLength.Length; j++) {
 
612
                                                                var len = foundMatchLength [j];
 
613
                                                                if (len > 0) {
 
614
                                                                        AddChunk (ref curChunk, len, GetChunkStyleColor (foundMatch.Groups [j - 1]));
 
615
                                                                        i += len - 1;
 
616
                                                                        curChunk.Length = 0;
 
617
                                                                }
 
618
                                                        }
 
619
                                                        return;
 
620
                                                }
 
621
                                                if (foundMatchLength[0] > 0) {
 
622
                                                        AddChunk (ref curChunk, foundMatchLength[0], GetChunkStyleColor (foundMatch.Color));
 
623
                                                        i += foundMatchLength[0] - 1;
 
624
                                                        curChunk.Length = 0;
 
625
                                                        return;
 
626
                                                }
611
627
                                        }
612
628
                                }
613
629
                                wordbuilder.Append (ch);
614
630
                                curChunk.Length = i - curChunk.Offset + 1;
 
631
                                if (!isWordPart) {
 
632
                                        AddChunk (ref curChunk, 0, curChunk.Style = GetStyle (curChunk) ?? GetSpanStyle ());
 
633
                                }
 
634
 
615
635
                        }
616
636
 
617
637
                        protected virtual string GetStyle (Chunk chunk)
640
660
                        }
641
661
                }
642
662
 
643
 
                public override Rule GetRule (TextDocument doc, string name)
 
663
                public override Rule GetRule (TextDocument document, string name)
644
664
                {
645
665
                        if (name == null || name == "<root>") {
646
666
                                return this;
647
667
                        }
648
 
                        if (name.StartsWith ("mode:"))
649
 
                                return SyntaxModeService.GetSyntaxMode (doc, name.Substring ("mode:".Length));
 
668
                        if (name.StartsWith ("mode:", StringComparison.Ordinal))
 
669
                                return SyntaxModeService.GetSyntaxMode (document, name.Substring ("mode:".Length));
650
670
 
651
671
                        foreach (Rule rule in rules) {
652
672
                                if (rule.Name == name)
700
720
 
701
721
                public const string MimeTypesAttribute = "mimeTypes";
702
722
 
703
 
                public static SyntaxMode Read (XmlReader reader)
 
723
                public static SyntaxMode Read (Stream stream)
704
724
                {
 
725
                        var reader = XmlReader.Create (stream);
705
726
                        var result = new SyntaxMode (null);
706
 
                        List<Match> matches = new List<Match> ();
707
 
                        List<Span> spanList = new List<Span> ();
708
 
                        List<Marker> prevMarkerList = new List<Marker> ();
 
727
                        var matches = new List<Match> ();
 
728
                        var spanList = new List<Span> ();
 
729
                        var prevMarkerList = new List<Marker> ();
709
730
                        XmlReadHelper.ReadList (reader, Node, delegate () {
710
731
                                if (reader == null)
711
732
                                        return true;
777
798
                
778
799
                Rule DeepCopy (TextDocument doc, SyntaxMode mode, Rule rule)
779
800
                {
780
 
                        Rule newRule = new Rule (mode);
 
801
                        var newRule = new Rule (mode);
781
802
                        newRule.spans = new Span[rule.Spans.Length];
782
803
                        for (int i = 0; i < rule.Spans.Length; i++) {
783
804
                                newRule.spans [i] = rule.Spans [i].Clone ();