aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Search/RegexSearchStrategy.cs
blob: e7ca7f8ce1f2d25dec938b9290e492576b3aa6c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Documents;

using Tango.Scripting.Editors.Document;

namespace Tango.Scripting.Editors.Search
{
	class RegexSearchStrategy : ISearchStrategy
	{
		readonly Regex searchPattern;
		readonly bool matchWholeWords;
		
		public RegexSearchStrategy(Regex searchPattern, bool matchWholeWords)
		{
			if (searchPattern == null)
				throw new ArgumentNullException("searchPattern");
			this.searchPattern = searchPattern;
			this.matchWholeWords = matchWholeWords;
		}
		
		public IEnumerable<ISearchResult> FindAll(ITextSource document, int offset, int length)
		{
			int endOffset = offset + length;
			foreach (Match result in searchPattern.Matches(document.Text)) {
				int resultEndOffset = result.Length + result.Index;
				if (offset > result.Index || endOffset < resultEndOffset)
					continue;
				if (matchWholeWords && (!IsWordBorder(document, result.Index) || !IsWordBorder(document, resultEndOffset)))
					continue;
				yield return new SearchResult { StartOffset = result.Index, Length = result.Length, Data = result };
			}
		}
		
		static bool IsWordBorder(ITextSource document, int offset)
		{
			return TextUtilities.GetNextCaretPosition(document, offset - 1, LogicalDirection.Forward, CaretPositioningMode.WordBorder) == offset;
		}
		
		public ISearchResult FindNext(ITextSource document, int offset, int length)
		{
			return FindAll(document, offset, length).FirstOrDefault();
		}
		
		public bool Equals(ISearchStrategy other)
		{
			var strategy = other as RegexSearchStrategy;
			return strategy != null &&
				strategy.searchPattern.ToString() == searchPattern.ToString() &&
				strategy.searchPattern.Options == searchPattern.Options &&
				strategy.searchPattern.RightToLeft == searchPattern.RightToLeft;
		}
	}
	
	class SearchResult : TextSegment, ISearchResult
	{
		public Match Data { get; set; }
		
		public string ReplaceWith(string replacement)
		{
			return Data.Result(replacement);
		}
	}
}
span> 0) return r; if (IsEnd != other.IsEnd) { if (IsEnd) return -1; else return 1; } else { if (IsEnd) return other.Nesting.CompareTo(Nesting); else return Nesting.CompareTo(other.Nesting); } } } /// <summary> /// Produces HTML code for the line, with &lt;span class="colorName"&gt; tags. /// </summary> public string ToHtml(HtmlOptions options) { int startOffset = this.DocumentLine.Offset; return ToHtml(startOffset, startOffset + this.DocumentLine.Length, options); } /// <summary> /// Produces HTML code for a section of the line, with &lt;span class="colorName"&gt; tags. /// </summary> public string ToHtml(int startOffset, int endOffset, HtmlOptions options) { if (options == null) throw new ArgumentNullException("options"); int documentLineStartOffset = this.DocumentLine.Offset; int documentLineEndOffset = documentLineStartOffset + this.DocumentLine.Length; if (startOffset < documentLineStartOffset || startOffset > documentLineEndOffset) throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between " + documentLineStartOffset + " and " + documentLineEndOffset); if (endOffset < startOffset || endOffset > documentLineEndOffset) throw new ArgumentOutOfRangeException("endOffset", endOffset, "Value must be between startOffset and " + documentLineEndOffset); ISegment requestedSegment = new SimpleSegment(startOffset, endOffset - startOffset); List<HtmlElement> elements = new List<HtmlElement>(); for (int i = 0; i < this.Sections.Count; i++) { HighlightedSection s = this.Sections[i]; if (s.GetOverlap(requestedSegment).Length > 0) { elements.Add(new HtmlElement(s.Offset, i, false, s.Color)); elements.Add(new HtmlElement(s.Offset + s.Length, i, true, s.Color)); } } elements.Sort(); TextDocument document = this.Document; StringWriter w = new StringWriter(CultureInfo.InvariantCulture); int textOffset = startOffset; foreach (HtmlElement e in elements) { int newOffset = Math.Min(e.Offset, endOffset); if (newOffset > startOffset) { HtmlClipboard.EscapeHtml(w, document.GetText(textOffset, newOffset - textOffset), options); } textOffset = Math.Max(textOffset, newOffset); if (options.ColorNeedsSpanForStyling(e.Color)) { if (e.IsEnd) { w.Write("</span>"); } else { w.Write("<span"); options.WriteStyleAttributeForColor(w, e.Color); w.Write('>'); } } } HtmlClipboard.EscapeHtml(w, document.GetText(textOffset, endOffset - textOffset), options); return w.ToString(); } /// <inheritdoc/> public override string ToString() { return "[" + GetType().Name + " " + ToHtml(new HtmlOptions()) + "]"; } } }