/// <summary> /// Parses the specified line, searching for the start of a region. /// </summary> /// <param name="line">The line.</param> /// <param name="text">The text.</param> /// <param name="currentRegion">The current region.</param> /// <param name="regionStart">The region start.</param> /// <returns></returns> private static bool ParseRegionStart(ITextSnapshotLine line, string text, ref PartialRegion currentRegion, ref int regionStart) { var regionStartMatch = RegionRegex.RegionStart.Match(text); if (!regionStartMatch.Success) { return(false); } regionStart = regionStartMatch.Groups[1].Success ? regionStartMatch.Groups[1].Length : 0; var currentLevel = currentRegion != null ? currentRegion.Level : 1; currentRegion = new PartialRegion { Level = currentLevel + 1, StartLine = line.LineNumber, StartOffset = regionStart, PartialParent = currentRegion }; return(true); }
/// <summary> /// Parses the current snapshot of <see cref="_buffer"/>. /// </summary> private void Parse() { var snapshot = _buffer.CurrentSnapshot; var regions = new List <Region>(); PartialRegion currentRegion = null; foreach (var line in snapshot.Lines) { var regionStart = -1; var text = line.GetText(); if (!ParseRegionStart(line, text, ref currentRegion, ref regionStart)) { ParseRegionEnd(regions, line, text, ref currentRegion, ref regionStart); } } var oldSpans = new List <Span>(_regions .Select(r => AsSnapshotSpan(r, _snapshot) .TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive) .Span)); var newSpans = new List <Span>(regions .Select(r => AsSnapshotSpan(r, snapshot).Span)); var oldSpanCollection = new NormalizedSpanCollection(oldSpans); var newSpanCollection = new NormalizedSpanCollection(newSpans); var removed = NormalizedSpanCollection.Difference(oldSpanCollection, newSpanCollection); var changeStart = int.MaxValue; var changeEnd = -1; if (removed.Count > 0) { changeStart = removed[0].Start; changeEnd = removed[removed.Count - 1].End; } if (newSpans.Count > 0) { changeStart = Math.Min(changeStart, newSpans[0].Start); changeEnd = Math.Max(changeEnd, newSpans[newSpans.Count - 1].End); } _snapshot = snapshot; _regions.Clear(); _regions.AddRange(regions); if (changeStart <= changeEnd) { TagsChanged?.Invoke(this, new SnapshotSpanEventArgs(new SnapshotSpan(_snapshot, Span.FromBounds(changeStart, changeEnd)))); } }
/// <summary> /// Parses the specified line, searching for the end of a region. /// </summary> /// <param name="regions">The regions.</param> /// <param name="line">The line.</param> /// <param name="text">The text.</param> /// <param name="currentRegion">The current region.</param> /// <param name="regionStart">The region start.</param> private static void ParseRegionEnd(List <Region> regions, ITextSnapshotLine line, string text, ref PartialRegion currentRegion, ref int regionStart) { var regionEndMatch = RegionRegex.RegionEnd.Match(text); if (!regionEndMatch.Success) { return; } regionStart = regionEndMatch.Groups[1].Success ? regionEndMatch.Groups[1].Length : 0; if (currentRegion == null) { return; } regions.Add(new Region { Level = currentRegion.Level, StartLine = currentRegion.StartLine, StartOffset = currentRegion.StartOffset, EndLine = line.LineNumber }); currentRegion = currentRegion.PartialParent; }