Browse Source

simplify SearchManager API

pull/23/head
Siegfried Pammer 14 years ago
parent
commit
1b7aab3e1d
  1. 9
      src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs
  2. 85
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs
  3. 134
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs
  4. 20
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs
  5. 1
      src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj
  6. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs
  7. 11
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs

9
src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs

@ -2,6 +2,7 @@ @@ -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 @@ -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 @@ -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);
}
}

85
src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchLocation.cs

@ -0,0 +1,85 @@ @@ -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
{
/// <summary>
/// Describes a set of files or a file + selection to search in.
/// </summary>
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<FileName> GenerateFileList()
{
List<FileName> files = new List<FileName>();
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<ITextEditorProvider>())
files.Add(editor.TextEditor.FileName);
break;
case SearchTarget.WholeProject:
if (ProjectService.CurrentProject == null)
break;
foreach (FileProjectItem item in ProjectService.CurrentProject.Items.OfType<FileProjectItem>())
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<FileProjectItem>())
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();
}
}
}

134
src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs

@ -28,24 +28,18 @@ namespace SearchAndReplace @@ -28,24 +28,18 @@ namespace SearchAndReplace
public class SearchManager
{
#region FindAll
public static IObservable<SearchedFile> 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<SearchedFile> FindAllParallel(ISearchStrategy strategy, SearchLocation location, IProgressMonitor progressMonitor)
{
currentSearchRegion = null;
var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode);
ParseableFileContentFinder fileFinder = new ParseableFileContentFinder();
IEnumerable<FileName> 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<SearchedFile> 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<SearchedFile> FindAll(ISearchStrategy strategy, SearchLocation location, IProgressMonitor progressMonitor)
{
currentSearchRegion = null;
var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode);
ParseableFileContentFinder fileFinder = new ParseableFileContentFinder();
IEnumerable<FileName> 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<SearchedFile>, IDisposable
@ -195,18 +189,13 @@ namespace SearchAndReplace @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -512,45 +486,5 @@ namespace SearchAndReplace
SearchResultsPad.Instance.BringToFront();
}
#endregion
static IEnumerable<FileName> GenerateFileList(SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false)
{
List<FileName> files = new List<FileName>();
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<ITextEditorProvider>())
files.Add(editor.TextEditor.FileName);
break;
case SearchTarget.WholeProject:
if (ProjectService.CurrentProject == null)
break;
foreach (FileProjectItem item in ProjectService.CurrentProject.Items.OfType<FileProjectItem>())
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<FileProjectItem>())
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();
}
}
}

20
src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs

@ -95,7 +95,9 @@ namespace SearchAndReplace @@ -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 @@ -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 @@ -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 @@ -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 @@ -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();
}

1
src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj

@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
<Compile Include="Commands\SearchMainMenuCommands.cs" />
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Engine\Enums.cs" />
<Compile Include="Engine\SearchLocation.cs" />
<Compile Include="Engine\SearchManager.cs" />
<Compile Include="Gui\DefaultSearchResult.cs" />
<Compile Include="Gui\ObserverSearchResult.cs" />

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs

@ -12,7 +12,7 @@ namespace ICSharpCode.AvalonEdit.Search @@ -12,7 +12,7 @@ namespace ICSharpCode.AvalonEdit.Search
/// <summary>
/// Basic interface for search algorithms.
/// </summary>
public interface ISearchStrategy
public interface ISearchStrategy : IEquatable<ISearchStrategy>
{
/// <summary>
/// Finds all matches in the given ITextSource and the given range.

11
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs

@ -17,6 +17,8 @@ namespace ICSharpCode.AvalonEdit.Search @@ -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 @@ -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

Loading…
Cancel
Save