void HighlightLineInternal(DocumentLine line) { lineStartOffset = line.Offset; lineText = line.Text; position = 0; ResetColorStack(); HighlightingRuleSet currentRuleSet = this.CurrentRuleSet; Stack <Match[]> storedMatchArrays = new Stack <Match[]>(); Match[] matches = AllocateMatchArray(currentRuleSet.Spans.Count); Match endSpanMatch = null; while (true) { for (int i = 0; i < matches.Length; i++) { if (matches[i] == null || (matches[i].Success && matches[i].Index < position)) { matches[i] = currentRuleSet.Spans[i].StartExpression.Match(lineText, position); } } if (endSpanMatch == null && !spanStack.IsEmpty) { endSpanMatch = spanStack.Peek().EndExpression.Match(lineText, position); } Match firstMatch = Minimum(matches, endSpanMatch); if (firstMatch == null) { break; } HighlightNonSpans(firstMatch.Index); Debug.Assert(position == firstMatch.Index); if (firstMatch == endSpanMatch) { PopColor(); // pop SpanColor HighlightingSpan poppedSpan = spanStack.Peek(); PushColor(poppedSpan.EndColor); position = firstMatch.Index + firstMatch.Length; PopColor(); // pop EndColor spanStack = spanStack.Pop(); currentRuleSet = this.CurrentRuleSet; //FreeMatchArray(matches); if (storedMatchArrays.Count > 0) { matches = storedMatchArrays.Pop(); int index = currentRuleSet.Spans.IndexOf(poppedSpan); Debug.Assert(index >= 0 && index < matches.Length); if (matches[index].Index == position) { throw new InvalidOperationException( "A highlighting span matched 0 characters, which would cause an endlees loop.\n" + "Change the highlighting definition so that either the start or the end regex matches at least one character.\n" + "Start regex: " + poppedSpan.StartExpression + "\n" + "End regex: " + poppedSpan.EndExpression); } } else { matches = AllocateMatchArray(currentRuleSet.Spans.Count); } } else { int index = Array.IndexOf(matches, firstMatch); Debug.Assert(index >= 0); HighlightingSpan newSpan = currentRuleSet.Spans[index]; spanStack = spanStack.Push(newSpan); currentRuleSet = this.CurrentRuleSet; storedMatchArrays.Push(matches); matches = AllocateMatchArray(currentRuleSet.Spans.Count); PushColor(newSpan.StartColor); position = firstMatch.Index + firstMatch.Length; PopColor(); PushColor(newSpan.SpanColor); } endSpanMatch = null; } HighlightNonSpans(line.Length); PopAllColors(); }
private IEnumerable<HighlightingRuleSet> GetRuleSets(HighlightingSpan span) { if (span.RuleSet == null) yield break; yield return span.RuleSet; foreach (var ruleSet in span.RuleSet.Spans.SelectMany(GetRuleSets)) { yield return ruleSet; } }
private IEnumerable<HighlightingColor> GetColors(HighlightingSpan span) { yield return span.SpanColor; yield return span.StartColor; yield return span.EndColor; if (span.RuleSet == null) yield break; foreach (var rule in span.RuleSet.Rules) { yield return rule.Color; } foreach (var color in span.RuleSet.Spans.SelectMany(GetColors)) { yield return color; } }
public HighlightingDefinition AddSpan(HighlightingSpan span) { MainRuleSet.Spans.Add(span); foreach (var color in GetColors(span)) { AddColor(color); } foreach (var ruleSet in GetRuleSets(span)) { AddRuleSet(ruleSet); } return this; }
public HighlightingDefinition AddSpan(string startExpression, string endExpression, HighlightingColor color) { var span = new HighlightingSpan { StartExpression = startExpression.ToRegex(), EndExpression = endExpression.ToRegex(), SpanColor = color, SpanColorIncludesStart = true, SpanColorIncludesEnd = true }; return AddSpan(span); }
public HighlightingSpan GetSpan() { var span = new HighlightingSpan(); if (!Reference.IsBlank()) { Name = Reference + "-syntax"; } span.SpanColor = GetColor(); span.StartColor = span.EndColor = span.SpanColor; span.StartExpression = GetRegexFromString(Start); span.EndExpression = GetRegexFromString(End); span.RuleSet = GetRuleSetFromSyntax(); if (!Escape.IsBlank()) { if (Escape == "\\") Escape = "\\\\"; if (span.RuleSet == null) span.RuleSet = new HighlightingRuleSet(); span.RuleSet.Spans.Add(new HighlightingSpan { StartExpression = GetRegexFromString(Escape), EndExpression = GetRegexFromString(".") }); } return span; }