From 1b7aab3e1d4c3131b951e065d3ca40ba02d5af51 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 26 Oct 2011 16:28:59 +0200 Subject: [PATCH] simplify SearchManager API --- .../Commands/SearchMainMenuCommands.cs | 9 +- .../Project/Engine/SearchLocation.cs | 85 +++++++++++ .../Project/Engine/SearchManager.cs | 134 +++++------------- .../Project/Gui/SearchAndReplacePanel.cs | 20 ++- .../Project/SearchAndReplace.csproj | 1 + .../Search/ISearchStrategy.cs | 2 +- .../Search/RegexSearchStrategy.cs | 11 ++ 7 files changed, 154 insertions(+), 108 deletions(-) create mode 100644 src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs b/src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs index 89ac24d56e..0c67085e61 100644 --- a/src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs +++ b/src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Search; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Editor; @@ -39,7 +40,9 @@ namespace SearchAndReplace public override void Run() { if (SearchOptions.CurrentFindPattern.Length > 0) { - var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, SearchOptions.SearchTarget == SearchTarget.CurrentSelection ? SearchManager.GetActiveSelection() : null); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + var result = SearchManager.FindNext(strategy, location); SearchManager.SelectResult(result); } else { Find find = new Find(); @@ -93,7 +96,9 @@ namespace SearchAndReplace if (SearchOptions.SearchTarget == SearchTarget.CurrentSelection) { SearchOptions.SearchTarget = SearchTarget.CurrentDocument; } - var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, SearchOptions.SearchTarget == SearchTarget.CurrentSelection ? SearchManager.GetActiveSelection() : null); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + var result = SearchManager.FindNext(strategy, location); SearchManager.SelectResult(result); } } diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs new file mode 100644 index 0000000000..26572903bb --- /dev/null +++ b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs @@ -0,0 +1,85 @@ +// 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.IO; +using System.Linq; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; + +namespace SearchAndReplace +{ + /// + /// Describes a set of files or a file + selection to search in. + /// + public class SearchLocation + { + public SearchTarget Target { get; private set; } + public string BaseDirectory { get; private set; } + public string Filter { get; private set; } + public bool SearchSubdirs { get; private set; } + public ISegment Selection { get; private set; } + + public SearchLocation(SearchTarget target, string baseDirectory, string filter, bool searchSubdirs, ISegment selection) + { + this.Target = target; + this.BaseDirectory = baseDirectory; + this.Filter = filter ?? "*.*"; + this.SearchSubdirs = searchSubdirs; + this.Selection = selection; + } + + public bool EqualsWithoutSelection(SearchLocation other) + { + return other != null && + Target == other.Target && + BaseDirectory == other.BaseDirectory && + Filter == other.Filter && + SearchSubdirs == other.SearchSubdirs; + } + + public virtual IEnumerable GenerateFileList() + { + List files = new List(); + + switch (Target) { + case SearchTarget.CurrentDocument: + case SearchTarget.CurrentSelection: + ITextEditorProvider vc = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; + if (vc != null) + files.Add(vc.TextEditor.FileName); + break; + case SearchTarget.AllOpenFiles: + foreach (ITextEditorProvider editor in WorkbenchSingleton.Workbench.ViewContentCollection.OfType()) + files.Add(editor.TextEditor.FileName); + break; + case SearchTarget.WholeProject: + if (ProjectService.CurrentProject == null) + break; + foreach (FileProjectItem item in ProjectService.CurrentProject.Items.OfType()) + files.Add(new FileName(item.FileName)); + break; + case SearchTarget.WholeSolution: + if (ProjectService.OpenSolution == null) + break; + foreach (var item in ProjectService.OpenSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items)) + files.Add(new FileName(Path.Combine(ProjectService.OpenSolution.Directory, item.Location))); + foreach (var item in ProjectService.OpenSolution.Projects.SelectMany(p => p.Items).OfType()) + files.Add(new FileName(item.FileName)); + break; + case SearchTarget.Directory: + if (!Directory.Exists(BaseDirectory)) + break; + return FileUtility.LazySearchDirectory(BaseDirectory, Filter, SearchSubdirs); + default: + throw new Exception("Invalid value for FileListType"); + } + + return files.Distinct(); + } + } +} diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs index 77663f0490..ac34a7f1c4 100644 --- a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs +++ b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs @@ -28,24 +28,18 @@ namespace SearchAndReplace public class SearchManager { #region FindAll - public static IObservable FindAllParallel(IProgressMonitor progressMonitor, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, - SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false, ISegment selection = null) + public static IObservable FindAllParallel(ISearchStrategy strategy, SearchLocation location, IProgressMonitor progressMonitor) { currentSearchRegion = null; - var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode); ParseableFileContentFinder fileFinder = new ParseableFileContentFinder(); - IEnumerable fileList = GenerateFileList(target, baseDirectory, filter, searchSubdirs); - return new SearchRun(strategy, fileFinder, fileList, progressMonitor) { Target = target, Selection = selection }; + return new SearchRun(strategy, fileFinder, location.GenerateFileList(), progressMonitor) { Target = location.Target, Selection = location.Selection }; } - public static IEnumerable FindAll(IProgressMonitor progressMonitor, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, - SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false, ISegment selection = null) + public static IEnumerable FindAll(ISearchStrategy strategy, SearchLocation location, IProgressMonitor progressMonitor) { currentSearchRegion = null; - var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode); ParseableFileContentFinder fileFinder = new ParseableFileContentFinder(); - IEnumerable fileList = GenerateFileList(target, baseDirectory, filter, searchSubdirs); - return new SearchRun(strategy, fileFinder, fileList, progressMonitor) { Target = target, Selection = selection }.GetResults(); + return new SearchRun(strategy, fileFinder, location.GenerateFileList(), progressMonitor) { Target = location.Target, Selection = location.Selection }.GetResults(); } class SearchRun : IObservable, IDisposable @@ -195,18 +189,13 @@ namespace SearchAndReplace #region FindNext static SearchRegion currentSearchRegion; - public static SearchResultMatch FindNext(string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, - SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false) + public static SearchResultMatch FindNext(ISearchStrategy strategy, SearchLocation location) { - if (string.IsNullOrEmpty(pattern)) - return null; - var files = GenerateFileList(target, baseDirectory, filter, searchSubdirs).ToArray(); + var files = location.GenerateFileList().ToArray(); if (files.Length == 0) return null; - if (currentSearchRegion == null || !currentSearchRegion.IsSameState(files, pattern, ignoreCase, matchWholeWords, mode, - target, baseDirectory, filter, searchSubdirs)) - currentSearchRegion = SearchRegion.CreateSearchRegion(files, pattern, ignoreCase, matchWholeWords, mode, - target, baseDirectory, filter, searchSubdirs); + if (currentSearchRegion == null || !currentSearchRegion.IsSameState(files, strategy, location)) + currentSearchRegion = SearchRegion.CreateSearchRegion(files, strategy, location); if (currentSearchRegion == null) return null; var result = currentSearchRegion.FindNext(); @@ -218,7 +207,7 @@ namespace SearchAndReplace class SearchRegion { FileName[] files; - AnchorSegment selection; + SearchLocation location; ISearchStrategy strategy; public SearchResultMatch FindNext() @@ -242,9 +231,9 @@ namespace SearchAndReplace int length; // if (target == SearchTarget.CurrentSelection) selection will not be null // hence use the selection as search region. - if (selection != null) { - searchOffset = Math.Max(selection.Offset, searchOffset); - length = selection.EndOffset - searchOffset; + if (location.Selection != null) { + searchOffset = Math.Max(location.Selection.Offset, searchOffset); + length = location.Selection.EndOffset - searchOffset; } else { length = document.TextLength - searchOffset; } @@ -264,9 +253,9 @@ namespace SearchAndReplace if (buffer == null) continue; int length; - if (selection != null) { - searchOffset = selection.Offset; - length = selection.Length; + if (location.Selection != null) { + searchOffset = location.Selection.Offset; + length = location.Selection.Length; } else { searchOffset = 0; length = buffer.TextLength; @@ -300,56 +289,30 @@ namespace SearchAndReplace return files.FindIndex(file => editor.FileName.Equals(file)); } - public static SearchRegion CreateSearchRegion(FileName[] files, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, SearchTarget target, string baseDirectory, string filter, bool searchSubdirs) + public static SearchRegion CreateSearchRegion(FileName[] files, ISearchStrategy strategy, SearchLocation location) { ITextEditor editor = GetActiveTextEditor(); if (editor != null) { - var document = new TextDocument(DocumentUtilitites.GetTextSource(editor.Document)); - AnchorSegment selection = null; - if (target == SearchTarget.CurrentSelection) - selection = new AnchorSegment(document, editor.SelectionStart, editor.SelectionLength); - return new SearchRegion(files, selection, pattern, ignoreCase, matchWholeWords, mode, target, baseDirectory, filter, searchSubdirs) { strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode) }; + return new SearchRegion(files, strategy, location); } return null; } - SearchRegion(FileName[] files, AnchorSegment selection, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, SearchTarget target, string baseDirectory, string filter, bool searchSubdirs) + SearchRegion(FileName[] files, ISearchStrategy strategy, SearchLocation location) { if (files == null) throw new ArgumentNullException("files"); this.files = files; - this.selection = selection; - this.pattern = pattern; - this.ignoreCase = ignoreCase; - this.matchWholeWords = matchWholeWords; - this.mode = mode; - this.target = target; - this.baseDirectory = baseDirectory; - this.filter = filter; - this.searchSubdirs = searchSubdirs; + this.strategy = strategy; + this.location = location; } - string pattern; - bool ignoreCase; - bool matchWholeWords; - SearchMode mode; - SearchTarget target; - string baseDirectory; - string filter; - bool searchSubdirs; - - public bool IsSameState(FileName[] files, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, SearchTarget target, string baseDirectory, string filter, bool searchSubdirs) + public bool IsSameState(FileName[] files, ISearchStrategy strategy, SearchLocation location) { return this.files.SequenceEqual(files) && - pattern == this.pattern && - ignoreCase == this.ignoreCase && - matchWholeWords == this.matchWholeWords && - mode == this.mode && - target == this.target && - baseDirectory == this.baseDirectory && - filter == this.filter && - searchSubdirs == this.searchSubdirs; + this.strategy.Equals(strategy) && + this.location.EqualsWithoutSelection(location); } } #endregion @@ -443,6 +406,17 @@ namespace SearchAndReplace return null; } } + + public static ISegment GetActiveSelection() + { + ITextEditor editor = GetActiveTextEditor(); + if (editor != null) { + var document = new TextDocument(DocumentUtilitites.GetTextSource(editor.Document)); + return new AnchorSegment(document, editor.SelectionStart, editor.SelectionLength); + } + + return null; + } #endregion #region Show Messages @@ -512,45 +486,5 @@ namespace SearchAndReplace SearchResultsPad.Instance.BringToFront(); } #endregion - - static IEnumerable GenerateFileList(SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false) - { - List files = new List(); - - switch (target) { - case SearchTarget.CurrentDocument: - case SearchTarget.CurrentSelection: - ITextEditorProvider vc = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; - if (vc != null) - files.Add(vc.TextEditor.FileName); - break; - case SearchTarget.AllOpenFiles: - foreach (ITextEditorProvider editor in WorkbenchSingleton.Workbench.ViewContentCollection.OfType()) - files.Add(editor.TextEditor.FileName); - break; - case SearchTarget.WholeProject: - if (ProjectService.CurrentProject == null) - break; - foreach (FileProjectItem item in ProjectService.CurrentProject.Items.OfType()) - files.Add(new FileName(item.FileName)); - break; - case SearchTarget.WholeSolution: - if (ProjectService.OpenSolution == null) - break; - foreach (var item in ProjectService.OpenSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items)) - files.Add(new FileName(Path.Combine(ProjectService.OpenSolution.Directory, item.Location))); - foreach (var item in ProjectService.OpenSolution.Projects.SelectMany(p => p.Items).OfType()) - files.Add(new FileName(item.FileName)); - break; - case SearchTarget.Directory: - if (!Directory.Exists(baseDirectory)) - break; - return FileUtility.LazySearchDirectory(baseDirectory, filter, searchSubdirs); - default: - throw new Exception("Invalid value for FileListType"); - } - - return files.Distinct(); - } } } diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs b/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs index ea295a41a3..2f0527aa92 100644 --- a/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs +++ b/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs @@ -95,7 +95,9 @@ namespace SearchAndReplace void FindNextButtonClicked(object sender, EventArgs e) { WritebackOptions(); - lastMatch = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + lastMatch = SearchManager.FindNext(strategy, location); SearchManager.SelectResult(lastMatch); Focus(); } @@ -106,7 +108,9 @@ namespace SearchAndReplace var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(); monitor.TaskName = StringParser.Parse("${res:AddIns.SearchReplace.SearchProgressTitle}"); try { - var results = SearchManager.FindAllParallel(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + var results = SearchManager.FindAllParallel(strategy, location, monitor); SearchManager.ShowSearchResults(SearchOptions.FindPattern, results); } catch (OperationCanceledException) {} } @@ -117,7 +121,9 @@ namespace SearchAndReplace var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(); monitor.TaskName = StringParser.Parse("${res:AddIns.SearchReplace.SearchProgressTitle}"); try { - var results = SearchManager.FindAllParallel(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + var results = SearchManager.FindAllParallel(strategy, location, monitor); SearchManager.MarkAll(results); } catch (OperationCanceledException) {} } @@ -129,7 +135,9 @@ namespace SearchAndReplace AsynchronousWaitDialog.RunInCancellableWaitDialog( StringParser.Parse("${res:AddIns.SearchReplace.SearchProgressTitle}"), null, monitor => { - var results = SearchManager.FindAll(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + var results = SearchManager.FindAll(strategy, location, monitor); count = SearchManager.ReplaceAll(results, SearchOptions.ReplacePattern, monitor.CancellationToken); }); if (count != -1) @@ -141,7 +149,9 @@ namespace SearchAndReplace WritebackOptions(); if (SearchManager.IsResultSelected(lastMatch)) SearchManager.Replace(lastMatch, SearchOptions.ReplacePattern); - lastMatch = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories); + var location = new SearchLocation(SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection); + var strategy = SearchStrategyFactory.Create(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchMode); + lastMatch = SearchManager.FindNext(strategy, location); SearchManager.SelectResult(lastMatch); Focus(); } diff --git a/src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj b/src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj index 199f3abfec..560b723cbb 100644 --- a/src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj +++ b/src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj @@ -70,6 +70,7 @@ + diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs index b8f1d7e7b1..039608208b 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs @@ -12,7 +12,7 @@ namespace ICSharpCode.AvalonEdit.Search /// /// Basic interface for search algorithms. /// - public interface ISearchStrategy + public interface ISearchStrategy : IEquatable { /// /// Finds all matches in the given ITextSource and the given range. diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs index 89d4d8a6fe..a2535ac394 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs @@ -17,6 +17,8 @@ namespace ICSharpCode.AvalonEdit.Search public RegexSearchStrategy(Regex searchPattern) { + if (searchPattern == null) + throw new ArgumentNullException("searchPattern"); this.searchPattern = searchPattern; } @@ -33,6 +35,15 @@ namespace ICSharpCode.AvalonEdit.Search { 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