private void AdvanceToSnapshot(ITextSnapshot snapshot) { if ((_searchSpans != null) && (_searchSpans.Count > 0) && (_searchSpans[0].Snapshot != snapshot)) { NormalizedSpanCollection newSpans = TextSearchNavigator.TranslateTo(_searchSpans[0].Snapshot, _searchSpans, snapshot); this.SearchSpans = new NormalizedSnapshotSpanCollection(snapshot, newSpans); } }
internal ITextSnapshot AdvanceToCurrentSnapshot() { //We don't need to take a snapshot of the results because the results are only modified on this thread. ITextSnapshot oldSnapshot = _results.Snapshot; ITextSnapshot newSnapshot = _buffer.CurrentSnapshot; if (oldSnapshot != newSnapshot) { //The results are all on an old snapshot. We need to project them forward (even though that might cause some stale and incorrect //results). NormalizedSpanCollection newMatches = TextSearchNavigator.TranslateTo(oldSnapshot, _results.Matches, newSnapshot); NormalizedSpanCollection newSearchedSpans = NormalizedSpanCollection.Empty; if ((_results.SearchedSpans.Count != 0) && !_options.HasFlag(FindOptions.Multiline)) { //Advance our record of the spans that have already been searched to the new snapshot as well. newSearchedSpans = BackgroundSearch <T> .TranslateToAndExtend(oldSnapshot, _results.SearchedSpans, newSnapshot); //But remove anything on a TextSnapshotLine that was modified by the change. List <Span> changedSpansOnNewSnapshot = new List <Span>(); ITextVersion version = oldSnapshot.Version; while (version != newSnapshot.Version) { foreach (var change in version.Changes) { changedSpansOnNewSnapshot.Add(BackgroundSearch <T> .Extend(newSnapshot, Tracking.TrackSpanForwardInTime(SpanTrackingMode.EdgeInclusive, change.NewSpan, version.Next, newSnapshot.Version))); } version = version.Next; } if (changedSpansOnNewSnapshot.Count > 0) { NormalizedSpanCollection changes = new NormalizedSpanCollection(changedSpansOnNewSnapshot); //Remove the spans touched by changes from the spans we've searched newSearchedSpans = NormalizedSpanCollection.Difference(newSearchedSpans, changes); } } _results = new SearchResults(newSnapshot, newMatches, newSearchedSpans); } return(newSnapshot); }
public bool Replace() { if (this.ReplaceTerm == null) { throw new InvalidOperationException("Can't replace with a null value. Set ReplaceTerm before performing a replace operation."); } if (!this.CurrentResult.HasValue) { throw new InvalidOperationException("Need to have a current result before being able to replace. Perform a FindNext or FindPrevious operation first."); } bool forward = (this.SearchOptions & FindOptions.SearchReverse) != FindOptions.SearchReverse; bool regEx = (this.SearchOptions & FindOptions.UseRegularExpressions) == FindOptions.UseRegularExpressions; //This may not be the text buffer's current snapshot but that is the desired behavior. We're replacing the current result //with the replace tuern. SnapshotSpan result = this.CurrentResult.Value; ITextSnapshot replaceSnapshot = result.Snapshot; SnapshotPoint searchStart = forward ? result.Start : result.End; SnapshotSpan searchSpan; NormalizedSnapshotSpanCollection searchSpans = this.SearchSpans; if ((searchSpans != null) && (searchSpans.Count > 0)) { //There could be a version skew here. if (searchSpans[0].Snapshot != replaceSnapshot) { searchSpans = new NormalizedSnapshotSpanCollection(replaceSnapshot, TextSearchNavigator.TranslateTo(searchSpans[0].Snapshot, searchSpans, replaceSnapshot)); } int index; if (!TextSearchNavigator.TryGetIndexOfContainingSpan(searchSpans, searchStart, out index)) { // If the match is outside of the search range, then we should noop return(false); } searchSpan = searchSpans[index]; } else { searchSpan = new SnapshotSpan(replaceSnapshot, 0, replaceSnapshot.Length); } searchSpan = forward ? new SnapshotSpan(searchStart, searchSpan.End) : new SnapshotSpan(searchSpan.Start, searchStart); //Ask the search engine to find the actual span we need to replace (& the corresponding replacement string). string replacementValue = null; SnapshotSpan?toReplace = _textSearchService.FindForReplace(searchSpan, this.SearchTerm, this.ReplaceTerm, this.SearchOptions, out replacementValue); if (toReplace.HasValue) { using (ITextEdit edit = _buffer.CreateEdit()) { Span replacementSpan = toReplace.Value.TranslateTo(edit.Snapshot, SpanTrackingMode.EdgeInclusive); if (!edit.Replace(replacementSpan, replacementValue)) { // The edit failed for some reason, perhaps read-only regions? return(false); } edit.Apply(); if (edit.Canceled) { // The edit failed, most likely a handler of the changed event forced the edit to be canceled. return(false); } } return(true); } return(false); }
public IEnumerable <ITagSpan <T> > GetTags(NormalizedSnapshotSpanCollection requestedSpans) { //We should always be called with a non-empty span. if (requestedSpans != null && requestedSpans.Count > 0) { ITextSnapshot searchSnapshot = _buffer.CurrentSnapshot; requestedSpans = new NormalizedSnapshotSpanCollection(searchSnapshot, TextSearchNavigator.TranslateTo(requestedSpans[0].Snapshot, requestedSpans, searchSnapshot)); if ((_searchSpans != null) && (_searchSpans.Count > 0)) { //The search has been narrowed via _searchSpan ... limit the request to the search range (after making sure it is on the correct snapshot). if (_searchSpans[0].Snapshot != searchSnapshot) { NormalizedSpanCollection newSpans = TextSearchNavigator.TranslateTo(_searchSpans[0].Snapshot, _searchSpans, searchSnapshot); _searchSpans = new NormalizedSnapshotSpanCollection(searchSnapshot, newSpans); } requestedSpans = new NormalizedSnapshotSpanCollection(searchSnapshot, NormalizedSpanCollection.Intersection(requestedSpans, _searchSpans)); if (requestedSpans.Count == 0) { yield break; } } foreach (var search in _searchTerms) { //Queue up a search if we need one. search.QueueSearch(requestedSpans); //Report any results from the search (if we've got them) var results = search.Results; if (results.Count > 0) { //Results could be on an old snapshot (and, if so, a new search has already been queued up) but we need to get the results on the current snapshot. if (results[0].Snapshot != searchSnapshot) { results = new NormalizedSnapshotSpanCollection(searchSnapshot, TextSearchNavigator.TranslateTo(results[0].Snapshot, results, searchSnapshot)); } if (_searchSpans != null) { results = new NormalizedSnapshotSpanCollection(searchSnapshot, NormalizedSpanCollection.Intersection(results, _searchSpans)); } int start = 0; foreach (var span in requestedSpans) { start = TextSearchTagger <T> .IndexOfContainingSpan(results, span.Start, start, false); if (start >= results.Count) { break; //All done. } int end = TextSearchTagger <T> .IndexOfContainingSpan(results, span.End, start, true); while (start < end) { T tag = search.TagFactory.Invoke(results[start]); if (tag != null) { yield return(new TagSpan <T>(results[start], tag)); } start++; } } } } } }