Browse Source

implement Replace and Replace all

pull/23/head
Siegfried Pammer 14 years ago
parent
commit
5989e5653e
  1. 8
      src/AddIns/Misc/SearchAndReplace/Project/Commands/SearchMainMenuCommands.cs
  2. 104
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs
  3. 94
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs
  4. 2
      src/AddIns/Misc/SearchAndReplace/Project/SearchOptions.cs
  5. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs
  6. 10
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs
  7. 38
      src/Main/Base/Project/Src/Editor/Search/SearchResultMatch.cs
  8. 2
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
  9. 16
      src/Main/Base/Project/Src/Util/ReactiveExtensions.cs

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

@ -39,7 +39,7 @@ namespace SearchAndReplace @@ -39,7 +39,7 @@ namespace SearchAndReplace
public override void Run()
{
if (SearchOptions.CurrentFindPattern.Length > 0) {
var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.DocumentIteratorType, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.SelectResult(result);
} else {
Find find = new Find();
@ -90,10 +90,10 @@ namespace SearchAndReplace @@ -90,10 +90,10 @@ namespace SearchAndReplace
if (textToFind != null && textToFind.Length > 0) {
SearchOptions.CurrentFindPattern = textToFind;
if (SearchOptions.DocumentIteratorType == SearchTarget.CurrentSelection) {
SearchOptions.DocumentIteratorType = SearchTarget.CurrentDocument;
if (SearchOptions.SearchTarget == SearchTarget.CurrentSelection) {
SearchOptions.SearchTarget = SearchTarget.CurrentDocument;
}
var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.DocumentIteratorType, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.SelectResult(result);
}
}

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

@ -75,17 +75,17 @@ namespace SearchAndReplace @@ -75,17 +75,17 @@ namespace SearchAndReplace
}
public static IObservable<SearchResultMatch> FindAll(string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode,
SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false)
SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false, bool useParallel = true, IProgressMonitor progressMonitor = null)
{
currentSearchRegion = null;
CancellationTokenSource cts = new CancellationTokenSource();
var monitor = WorkbenchSingleton.Workbench.StatusBar.CreateProgressMonitor(cts.Token);
CancellationToken ct = progressMonitor != null ? progressMonitor.CancellationToken : new CancellationTokenSource().Token;
var monitor = progressMonitor ?? WorkbenchSingleton.Workbench.StatusBar.CreateProgressMonitor(ct);
monitor.TaskName = "Find all occurrences of '" + pattern + "' in " + GetTargetDescription(target, baseDirectory);
monitor.Status = OperationStatus.Normal;
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, monitor, cts);
return new SearchRun(strategy, fileFinder, fileList, monitor);
}
static string GetTargetDescription(SearchTarget target, string baseDirectory = null)
@ -115,35 +115,40 @@ namespace SearchAndReplace @@ -115,35 +115,40 @@ namespace SearchAndReplace
ParseableFileContentFinder fileFinder;
IEnumerable<FileName> fileList;
IProgressMonitor monitor;
CancellationTokenSource cts;
int count;
public SearchRun(ISearchStrategy strategy, ParseableFileContentFinder fileFinder, IEnumerable<FileName> fileList, IProgressMonitor monitor, CancellationTokenSource cts)
public bool UseParallel { get; set; }
public SearchRun(ISearchStrategy strategy, ParseableFileContentFinder fileFinder, IEnumerable<FileName> fileList, IProgressMonitor monitor)
{
this.strategy = strategy;
this.fileFinder = fileFinder;
this.fileList = fileList;
this.monitor = monitor;
this.cts = cts;
}
public IDisposable Subscribe(IObserver<SearchResultMatch> observer)
{
this.observer = observer;
var task = new System.Threading.Tasks.Task(
delegate {
var list = fileList.ToList();
this.count = list.Count;
Parallel.ForEach(list, new ParallelOptions { CancellationToken = monitor.CancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount }, fileName => SearchFile(fileName, strategy, monitor.CancellationToken));
});
task.ContinueWith(t => { if (t.Exception != null) observer.OnError(t.Exception); else observer.OnCompleted(); this.Dispose(); });
task.Start();
if (UseParallel) {
var task = new System.Threading.Tasks.Task(
delegate {
var list = fileList.ToList();
this.count = list.Count;
Parallel.ForEach(list, new ParallelOptions { CancellationToken = monitor.CancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount }, fileName => SearchFile(fileName, strategy, monitor.CancellationToken));
});
task.ContinueWith(t => { if (t.Exception != null) observer.OnError(t.Exception); else observer.OnCompleted(); this.Dispose(); });
task.Start();
} else {
foreach (var file in fileList) {
SearchFile(file, strategy, monitor.CancellationToken);
}
}
return this;
}
public void Dispose()
{
cts.Cancel();
monitor.Dispose();
}
@ -169,7 +174,7 @@ namespace SearchAndReplace @@ -169,7 +174,7 @@ namespace SearchAndReplace
var start = document.GetLocation(result.Offset).ToLocation();
var end = document.GetLocation(result.Offset + result.Length).ToLocation();
lock (observer)
observer.OnNext(new SearchResultMatch(fileName, start, end, SearchResultsPad.CreateInlineBuilder(start, end, document, Path.GetExtension(fileName))));
observer.OnNext(new SearchResultMatch(fileName, start, end, result.Offset, result.Length, SearchResultsPad.CreateInlineBuilder(start, end, document, Path.GetExtension(fileName))));
}
lock (monitor)
monitor.Progress += 1.0 / count;
@ -280,7 +285,7 @@ namespace SearchAndReplace @@ -280,7 +285,7 @@ namespace SearchAndReplace
if (result != null) {
var start = document.OffsetToPosition(result.Offset);
var end = document.OffsetToPosition(result.EndOffset);
return new SearchResultMatch(file, start, end, null);
return new SearchResultMatch(file, start, end, result.Offset, result.Length, null);
}
return null;
}
@ -357,6 +362,30 @@ namespace SearchAndReplace @@ -357,6 +362,30 @@ namespace SearchAndReplace
);
}
public static void ReplaceAll(IObservable<SearchResultMatch> results, string replacement, CancellationToken ct)
{
var differences = new Dictionary<FileName, int>();
int count = 0;
results.ObserveOnUIThread()
.Subscribe(
match => {
ITextEditor textArea = OpenTextArea(match.FileName, false);
if (textArea != null) {
int difference = 0;
if (!differences.TryGetValue(match.FileName, out difference))
differences.Add(match.FileName, 0);
string newString = match.TransformReplacePattern(replacement);
textArea.Document.Replace(match.StartOffset + difference, match.Length, newString);
difference += newString.Length - match.Length;
differences[match.FileName] = difference;
count++;
}
},
error => MessageService.ShowException(error),
() => ShowReplaceDoneMessage(count)
);
}
static void MarkResult(SearchResultMatch result, bool switchToOpenedView = true)
{
ITextEditor textArea = OpenTextArea(result.FileName, switchToOpenedView);
@ -373,7 +402,7 @@ namespace SearchAndReplace @@ -373,7 +402,7 @@ namespace SearchAndReplace
BookmarkManager.AddMark(new Bookmark(result.FileName, result.StartLocation));
}
}
static ITextEditor OpenTextArea(string fileName, bool switchToOpenedView = true)
{
ITextEditorProvider textEditorProvider;
@ -389,6 +418,18 @@ namespace SearchAndReplace @@ -389,6 +418,18 @@ namespace SearchAndReplace
return null;
}
static void ShowReplaceDoneMessage(int count)
{
if (count == 0) {
ShowNotFoundMessage();
} else {
MessageService.ShowMessage(
StringParser.Parse("${res:ICSharpCode.TextEditor.Document.SearchReplaceManager.ReplaceAllDone}",
new StringTagPair("Count", count.ToString())),
"${res:Global.FinishedCaptionText}");
}
}
static void ShowMarkDoneMessage(int count)
{
if (count == 0) {
@ -400,12 +441,12 @@ namespace SearchAndReplace @@ -400,12 +441,12 @@ namespace SearchAndReplace
"${res:Global.FinishedCaptionText}");
}
}
static void ShowNotFoundMessage()
{
MessageService.ShowMessage("${res:Dialog.NewProject.SearchReplace.SearchStringNotFound}", "${res:Dialog.NewProject.SearchReplace.SearchStringNotFound.Title}");
}
public static void SelectResult(SearchResultMatch result)
{
if (result == null) {
@ -420,5 +461,26 @@ namespace SearchAndReplace @@ -420,5 +461,26 @@ namespace SearchAndReplace
editor.Select(start, end - start);
}
}
public static bool IsResultSelected(SearchResultMatch result)
{
if (result == null)
return false;
var editor = GetActiveTextEditor();
if (editor == null)
return false;
return result.FileName.Equals(editor.FileName)
&& result.StartOffset == editor.SelectionStart
&& result.Length == editor.SelectionLength;
}
public static void Replace(SearchResultMatch lastMatch, string replacement)
{
if (lastMatch == null)
return;
ITextEditor textArea = OpenTextArea(lastMatch.FileName);
if (textArea != null)
textArea.Document.Replace(lastMatch.StartOffset, lastMatch.Length, lastMatch.TransformReplacePattern(replacement));
}
}
}

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

@ -106,70 +106,46 @@ namespace SearchAndReplace @@ -106,70 +106,46 @@ namespace SearchAndReplace
}
}
SearchResultMatch lastMatch;
void FindNextButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
var result = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.DocumentIteratorType, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.SelectResult(result);
lastMatch = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.SelectResult(lastMatch);
Focus();
}
void FindAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(0);
}
} else {
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.DocumentIteratorType, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.ShowSearchResults(SearchOptions.FindPattern, results);
}
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.ShowSearchResults(SearchOptions.FindPattern, results);
}
void BookmarkAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(1);
}
} else {
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.DocumentIteratorType, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.MarkAll(results);
}
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.MarkAll(results);
}
void ReplaceAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(2);
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
// SearchReplaceManager.ReplaceAll(monitor);
}
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true)) {
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, false, monitor);
SearchManager.ReplaceAll(results, SearchOptions.ReplacePattern, monitor.CancellationToken);
}
}
void ReplaceButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
ReplaceInSelection();
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
// SearchReplaceManager.Replace(monitor);
}
}
if (SearchManager.IsResultSelected(lastMatch))
SearchManager.Replace(lastMatch, SearchOptions.ReplacePattern);
lastMatch = SearchManager.FindNext(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.SelectResult(lastMatch);
Focus();
}
@ -191,9 +167,9 @@ namespace SearchAndReplace @@ -191,9 +167,9 @@ namespace SearchAndReplace
SearchOptions.SearchStrategyType = (SearchMode)Get<ComboBox>("use").SelectedIndex;
if (Get<ComboBox>("lookIn").DropDownStyle == ComboBoxStyle.DropDown) {
SearchOptions.DocumentIteratorType = SearchTarget.Directory;
SearchOptions.SearchTarget = SearchTarget.Directory;
} else {
SearchOptions.DocumentIteratorType = (SearchTarget)Get<ComboBox>("lookIn").SelectedIndex;
SearchOptions.SearchTarget = (SearchTarget)Get<ComboBox>("lookIn").SelectedIndex;
}
}
@ -236,10 +212,10 @@ namespace SearchAndReplace @@ -236,10 +212,10 @@ namespace SearchAndReplace
if (IsMultipleLineSelection(SearchManager.GetActiveTextEditor())) {
SearchTarget = SearchTarget.CurrentSelection;
} else {
if (SearchOptions.DocumentIteratorType == SearchTarget.CurrentSelection) {
SearchOptions.DocumentIteratorType = SearchTarget.CurrentDocument;
if (SearchOptions.SearchTarget == SearchTarget.CurrentSelection) {
SearchOptions.SearchTarget = SearchTarget.CurrentDocument;
}
SearchTarget = SearchOptions.DocumentIteratorType;
SearchTarget = SearchOptions.SearchTarget;
}
Get<ComboBox>("fileTypes").Text = SearchOptions.LookInFiletypes;
@ -374,36 +350,6 @@ namespace SearchAndReplace @@ -374,36 +350,6 @@ namespace SearchAndReplace
RemoveActiveWindowChangedHandler();
}
/// <summary>
/// action: 0 = find, 1 = mark, 2 = replace
/// </summary>
void RunAllInSelection(int action)
{
const IProgressMonitor monitor = null;
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
textEditor.Select(startOffset, endOffset - startOffset);
try {
ignoreSelectionChanges = true;
if (action == 0) {
// SearchInFilesManager.FindAll(startOffset, endOffset - startOffset, monitor);
} else if (action == 1) {
// SearchReplaceManager.MarkAll(startOffset, endOffset - startOffset, monitor);
} else if (action == 2) {
// use anchor for endOffset because the replacement might change the text length
var anchor = textEditor.Document.CreateAnchor(endOffset);
// SearchReplaceManager.ReplaceAll(startOffset, endOffset - startOffset, monitor);
endOffset = anchor.Offset;
}
textEditor.Select(startOffset, endOffset - startOffset);
} finally {
ignoreSelectionChanges = false;
}
}
void ReplaceInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);

2
src/AddIns/Misc/SearchAndReplace/Project/SearchOptions.cs

@ -136,7 +136,7 @@ namespace SearchAndReplace @@ -136,7 +136,7 @@ namespace SearchAndReplace
}
}
public static SearchTarget DocumentIteratorType {
public static SearchTarget SearchTarget {
get {
return properties.Get("DocumentIteratorType", SearchTarget.CurrentDocument);
}

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

@ -36,7 +36,7 @@ namespace ICSharpCode.AvalonEdit.Search @@ -36,7 +36,7 @@ namespace ICSharpCode.AvalonEdit.Search
/// </summary>
public interface ISearchResult : ISegment
{
string ReplaceWith(string replacement);
}
/// <summary>

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

@ -4,7 +4,9 @@ @@ -4,7 +4,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using ICSharpCode.AvalonEdit.Document;
namespace ICSharpCode.AvalonEdit.Search
@ -22,7 +24,7 @@ namespace ICSharpCode.AvalonEdit.Search @@ -22,7 +24,7 @@ namespace ICSharpCode.AvalonEdit.Search
{
foreach (Match result in searchPattern.Matches(document.Text)) {
if (offset <= result.Index && (offset + length) >= (result.Index + result.Length))
yield return new SearchResult { StartOffset = result.Index, Length = result.Length };
yield return new SearchResult { StartOffset = result.Index, Length = result.Length, Data = result };
}
}
@ -34,5 +36,11 @@ namespace ICSharpCode.AvalonEdit.Search @@ -34,5 +36,11 @@ namespace ICSharpCode.AvalonEdit.Search
class SearchResult : TextSegment, ISearchResult
{
public Match Data { get; set; }
public string ReplaceWith(string replacement)
{
return Data.Result(replacement);
}
}
}

38
src/Main/Base/Project/Src/Editor/Search/SearchResultMatch.cs

@ -15,6 +15,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Search @@ -15,6 +15,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
public class SearchResultMatch
{
FileName fileName;
int offset;
int length;
Location startLocation;
Location endLocation;
HighlightedInlineBuilder builder;
@ -35,16 +37,30 @@ namespace ICSharpCode.SharpDevelop.Editor.Search @@ -35,16 +37,30 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
get { return builder; }
}
public int StartOffset {
get { return offset; }
}
public int Length {
get { return length; }
}
public int EndOffset {
get { return offset + length; }
}
public virtual string TransformReplacePattern(string pattern)
{
return pattern;
}
public SearchResultMatch(FileName fileName, Location startLocation, Location endLocation, HighlightedInlineBuilder builder)
public SearchResultMatch(FileName fileName, Location startLocation, Location endLocation, int offset, int length, HighlightedInlineBuilder builder)
{
this.fileName = fileName;
this.startLocation = startLocation;
this.endLocation = endLocation;
this.offset = offset;
this.length = length;
this.builder = builder;
}
@ -75,10 +91,26 @@ namespace ICSharpCode.SharpDevelop.Editor.Search @@ -75,10 +91,26 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
}
}
public SimpleSearchResultMatch(FileName fileName, Location position, string displayText)
: base(fileName, position, position, new HighlightedInlineBuilder(displayText))
public SimpleSearchResultMatch(FileName fileName, Location position, int offset, string displayText)
: base(fileName, position, position, offset, 0, null)
{
this.displayText = displayText;
}
}
public class RegexResultMatch : SearchResultMatch
{
ICSharpCode.AvalonEdit.Search.ISearchResult match;
public RegexResultMatch(FileName fileName, Location startLocation, Location endLocation, int offset, int length, HighlightedInlineBuilder builder, ICSharpCode.AvalonEdit.Search.ISearchResult match)
: base(fileName, startLocation, endLocation, offset, length, builder)
{
this.match = match;
}
public override string TransformReplacePattern(string pattern)
{
return match.ReplaceWith(pattern);
}
}
}

2
src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs

@ -376,7 +376,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -376,7 +376,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
var document = new TextDocument(DocumentUtilitites.GetTextSource(ParserService.GetParseableFileContent(r.FileName)));
var start = document.GetLocation(r.Offset).ToLocation();
var end = document.GetLocation(r.Offset + r.Length).ToLocation();
SearchResultMatch res = new SearchResultMatch(new FileName(r.FileName), start, end, SearchResultsPad.CreateInlineBuilder(start, end, document, Path.GetExtension(r.FileName)));
SearchResultMatch res = new SearchResultMatch(new FileName(r.FileName), start, end, r.Offset, r.Length, SearchResultsPad.CreateInlineBuilder(start, end, document, Path.GetExtension(r.FileName)));
results.Add(res);
}
SearchResultsPad.Instance.ShowSearchResults(title, results);

16
src/Main/Base/Project/Src/Util/ReactiveExtensions.cs

@ -2,7 +2,11 @@ @@ -2,7 +2,11 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Windows.Threading;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop
@ -30,6 +34,18 @@ namespace ICSharpCode.SharpDevelop @@ -30,6 +34,18 @@ namespace ICSharpCode.SharpDevelop
return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted));
}
public static List<T> ToList<T>(this IObservable<T> source, CancellationToken cancellation)
{
List<T> results = new List<T>();
ManualResetEventSlim ev = new ManualResetEventSlim();
Exception error = null;
using (source.Subscribe(item => results.Add(item), exception => { error = exception; ev.Set(); }, () => ev.Set()))
ev.Wait(cancellation);
if (error != null)
throw new TargetInvocationException(error);
return results;
}
class AnonymousObservable<T> : IObservable<T>
{
Func<IObserver<T>, IDisposable> subscribe;

Loading…
Cancel
Save