34 changed files with 384 additions and 2407 deletions
@ -1,124 +0,0 @@
@@ -1,124 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor; |
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class AllOpenDocumentIterator : IDocumentIterator |
||||
{ |
||||
int startIndex = -1; |
||||
int curIndex = -1; |
||||
bool resetted = true; |
||||
|
||||
public AllOpenDocumentIterator() |
||||
{ |
||||
Reset(); |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
IViewContent viewContent = GetCurrentTextEditorViewContent(); |
||||
if (viewContent != null) { |
||||
return viewContent.PrimaryFileName; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
IViewContent GetCurrentTextEditorViewContent() |
||||
{ |
||||
GetCurIndex(); |
||||
if (curIndex >= 0) { |
||||
IViewContent viewContent = WorkbenchSingleton.Workbench.ViewContentCollection.ToList()[curIndex]; |
||||
if (viewContent is ITextEditorProvider) { |
||||
return viewContent; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
IViewContent viewContent = GetCurrentTextEditorViewContent(); |
||||
if (viewContent != null) { |
||||
ITextEditor textEditor = (((ITextEditorProvider)viewContent).TextEditor); |
||||
return new ProvidedDocumentInformation(textEditor.Document, |
||||
CurrentFileName, |
||||
textEditor); |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
void GetCurIndex() |
||||
{ |
||||
IViewContent[] viewContentCollection = WorkbenchSingleton.Workbench.ViewContentCollection.ToArray(); |
||||
int viewCount = WorkbenchSingleton.Workbench.ViewContentCollection.Count; |
||||
if (curIndex == -1 || curIndex >= viewCount) { |
||||
for (int i = 0; i < viewCount; ++i) { |
||||
if (WorkbenchSingleton.Workbench.ActiveViewContent == viewContentCollection[i]) { |
||||
curIndex = i; |
||||
return; |
||||
} |
||||
} |
||||
curIndex = -1; |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
GetCurIndex(); |
||||
if (curIndex < 0) { |
||||
return false; |
||||
} |
||||
|
||||
if (resetted) { |
||||
resetted = false; |
||||
return true; |
||||
} |
||||
|
||||
curIndex = (curIndex + 1) % WorkbenchSingleton.Workbench.ViewContentCollection.Count; |
||||
if (curIndex == startIndex) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
GetCurIndex(); |
||||
if (curIndex < 0) { |
||||
return false; |
||||
} |
||||
if (resetted) { |
||||
resetted = false; |
||||
return true; |
||||
} |
||||
|
||||
if (curIndex == 0) { |
||||
curIndex = WorkbenchSingleton.Workbench.ViewContentCollection.Count - 1; |
||||
} |
||||
|
||||
if (curIndex > 0) { |
||||
--curIndex; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
curIndex = -1; |
||||
GetCurIndex(); |
||||
startIndex = curIndex; |
||||
resetted = true; |
||||
} |
||||
} |
||||
} |
@ -1,63 +0,0 @@
@@ -1,63 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor; |
||||
using System; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class CurrentDocumentIterator : IDocumentIterator |
||||
{ |
||||
bool didRead = false; |
||||
|
||||
public CurrentDocumentIterator() |
||||
{ |
||||
Reset(); |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
if (!SearchReplaceUtilities.IsTextAreaSelected) { |
||||
return null; |
||||
} |
||||
return WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName; |
||||
} |
||||
} |
||||
|
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
ITextEditor textEditor = SearchReplaceUtilities.GetActiveTextEditor(); |
||||
if (textEditor != null) |
||||
return new ProvidedDocumentInformation(textEditor.Document, CurrentFileName, textEditor); |
||||
else |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
if (!SearchReplaceUtilities.IsTextAreaSelected) { |
||||
return false; |
||||
} |
||||
if (didRead) { |
||||
return false; |
||||
} |
||||
didRead = true; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
return MoveForward(); |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
didRead = false; |
||||
} |
||||
} |
||||
} |
@ -1,100 +0,0 @@
@@ -1,100 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class DirectoryDocumentIterator : IDocumentIterator |
||||
{ |
||||
string searchDirectory; |
||||
string fileMask; |
||||
bool searchSubdirectories; |
||||
|
||||
List<string> files = null; |
||||
int curIndex = -1; |
||||
|
||||
public DirectoryDocumentIterator(string searchDirectory, string fileMask, bool searchSubdirectories) |
||||
{ |
||||
this.searchDirectory = searchDirectory; |
||||
this.fileMask = fileMask; |
||||
this.searchSubdirectories = searchSubdirectories; |
||||
|
||||
Reset(); |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
|
||||
return files[curIndex].ToString();; |
||||
} |
||||
} |
||||
|
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
string fileName = files[curIndex].ToString(); |
||||
if (!File.Exists(fileName) || !SearchReplaceUtilities.IsSearchable(fileName)) { |
||||
++curIndex; |
||||
return Current; |
||||
} |
||||
IDocument document; |
||||
foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) { |
||||
if (content.PrimaryFileName != null && |
||||
FileUtility.IsEqualFileName(content.PrimaryFileName, fileName) && |
||||
content is ITextEditorProvider) { |
||||
document = ((ITextEditorProvider)content).TextEditor.Document; |
||||
return new ProvidedDocumentInformation(document, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
ITextBuffer fileContent; |
||||
try { |
||||
fileContent = ParserService.GetParseableFileContent(fileName); |
||||
} catch (Exception) { |
||||
return null; |
||||
} |
||||
return new ProvidedDocumentInformation(fileContent, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
if (curIndex == -1) { |
||||
files = FileUtility.SearchDirectory(this.searchDirectory, this.fileMask, this.searchSubdirectories); |
||||
} |
||||
return ++curIndex < files.Count; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
if (curIndex == -1) { |
||||
curIndex = files.Count - 1; |
||||
return true; |
||||
} |
||||
return --curIndex >= -1; |
||||
} |
||||
|
||||
|
||||
public void Reset() |
||||
{ |
||||
curIndex = -1; |
||||
} |
||||
} |
||||
} |
@ -1,91 +0,0 @@
@@ -1,91 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public enum DocumentIteratorType { |
||||
CurrentDocument, |
||||
CurrentSelection, |
||||
AllOpenFiles, |
||||
WholeProject, |
||||
WholeSolution, |
||||
Directory // only used for search in files
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a bi-directional iterator which could move froward/backward
|
||||
/// in a document queue. Note that after move forward is called
|
||||
/// move backward needn't to function correctly either move forward or move
|
||||
/// backward is called but they're not mixed. After a reset the move operation
|
||||
/// can be switched.
|
||||
/// </summary>
|
||||
public interface IDocumentIterator |
||||
{ |
||||
/// <value>
|
||||
/// Returns the current ProvidedDocumentInformation. This method
|
||||
/// usually creates a new ProvidedDocumentInformation object which can
|
||||
/// be time consuming
|
||||
/// </value>
|
||||
ProvidedDocumentInformation Current { |
||||
get; |
||||
} |
||||
|
||||
/// <value>
|
||||
/// Returns the file name of the current provided document information. This
|
||||
/// property usually is not time consuming
|
||||
/// </value>
|
||||
string CurrentFileName { |
||||
get; |
||||
} |
||||
|
||||
/// <remarks>
|
||||
/// Moves the iterator one document forward.
|
||||
/// </remarks>
|
||||
bool MoveForward(); |
||||
|
||||
/// <remarks>
|
||||
/// Moves the iterator one document backward.
|
||||
/// </remarks>
|
||||
bool MoveBackward(); |
||||
|
||||
/// <remarks>
|
||||
/// Resets the iterator to the start position.
|
||||
/// </remarks>
|
||||
void Reset(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A document iterator which never returns any results.
|
||||
/// </summary>
|
||||
public sealed class DummyDocumentIterator : IDocumentIterator |
||||
{ |
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
} |
||||
} |
||||
} |
@ -1,99 +0,0 @@
@@ -1,99 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop; |
||||
using System; |
||||
using System.Collections; |
||||
using System.IO; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class WholeProjectDocumentIterator : IDocumentIterator |
||||
{ |
||||
ArrayList files = new ArrayList(); |
||||
int curIndex = -1; |
||||
|
||||
public WholeProjectDocumentIterator() |
||||
{ |
||||
Reset(); |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
|
||||
return files[curIndex].ToString();; |
||||
} |
||||
} |
||||
|
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
if (!File.Exists(files[curIndex].ToString())) { |
||||
++curIndex; |
||||
return Current; |
||||
} |
||||
IDocument document; |
||||
string fileName = files[curIndex].ToString(); |
||||
foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) { |
||||
if (content.PrimaryFileName != null && |
||||
FileUtility.IsEqualFileName(content.PrimaryFileName, fileName) && |
||||
content is ITextEditorProvider) |
||||
{ |
||||
document = (((ITextEditorProvider)content).TextEditor).Document; |
||||
return new ProvidedDocumentInformation(document, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
ITextBuffer fileContent; |
||||
try { |
||||
fileContent = ParserService.GetParseableFileContent(fileName); |
||||
} catch (Exception) { |
||||
return null; |
||||
} |
||||
return new ProvidedDocumentInformation(fileContent, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
return ++curIndex < files.Count; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
if (curIndex == -1) { |
||||
curIndex = files.Count - 1; |
||||
return true; |
||||
} |
||||
return --curIndex >= -1; |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
files.Clear(); |
||||
if (ProjectService.CurrentProject != null) { |
||||
foreach (ProjectItem item in ProjectService.CurrentProject.Items) { |
||||
if (item is FileProjectItem && SearchReplaceUtilities.IsSearchable(item.FileName)) { |
||||
files.Add(item.FileName); |
||||
} |
||||
} |
||||
} |
||||
|
||||
curIndex = -1; |
||||
} |
||||
} |
||||
} |
@ -1,101 +0,0 @@
@@ -1,101 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop; |
||||
using System; |
||||
using System.Collections; |
||||
using System.IO; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class WholeSolutionDocumentIterator : IDocumentIterator |
||||
{ |
||||
ArrayList files = new ArrayList(); |
||||
int curIndex = -1; |
||||
|
||||
public WholeSolutionDocumentIterator() |
||||
{ |
||||
Reset(); |
||||
} |
||||
|
||||
public string CurrentFileName { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
|
||||
return files[curIndex].ToString();; |
||||
} |
||||
} |
||||
|
||||
public ProvidedDocumentInformation Current { |
||||
get { |
||||
if (curIndex < 0 || curIndex >= files.Count) { |
||||
return null; |
||||
} |
||||
if (!File.Exists(files[curIndex].ToString())) { |
||||
++curIndex; |
||||
return Current; |
||||
} |
||||
IDocument document; |
||||
string fileName = files[curIndex].ToString(); |
||||
foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) { |
||||
if (content.PrimaryFileName != null && |
||||
FileUtility.IsEqualFileName(content.PrimaryFileName, fileName) && |
||||
content is ITextEditorProvider) |
||||
{ |
||||
document = (((ITextEditorProvider)content).TextEditor).Document; |
||||
return new ProvidedDocumentInformation(document, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
ITextBuffer fileContent; |
||||
try { |
||||
fileContent = ParserService.GetParseableFileContent(fileName); |
||||
} catch (Exception) { |
||||
return null; |
||||
} |
||||
return new ProvidedDocumentInformation(fileContent, |
||||
fileName, |
||||
0); |
||||
} |
||||
} |
||||
|
||||
public bool MoveForward() |
||||
{ |
||||
return ++curIndex < files.Count; |
||||
} |
||||
|
||||
public bool MoveBackward() |
||||
{ |
||||
if (curIndex == -1) { |
||||
curIndex = files.Count - 1; |
||||
return true; |
||||
} |
||||
return --curIndex >= -1; |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
files.Clear(); |
||||
if (ProjectService.OpenSolution != null) { |
||||
foreach (IProject project in ProjectService.OpenSolution.Projects) { |
||||
foreach (ProjectItem item in project.Items) { |
||||
if (item is FileProjectItem && SearchReplaceUtilities.IsSearchable(item.FileName)) { |
||||
files.Add(item.FileName); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
curIndex = -1; |
||||
} |
||||
} |
||||
} |
@ -1,16 +1,17 @@
@@ -1,16 +1,17 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// Builds a text iterator object.
|
||||
/// </summary>
|
||||
public interface ITextIteratorBuilder |
||||
public enum SearchTarget |
||||
{ |
||||
ITextIterator BuildTextIterator(ProvidedDocumentInformation info); |
||||
CurrentDocument, |
||||
CurrentSelection, |
||||
AllOpenFiles, |
||||
WholeProject, |
||||
WholeSolution, |
||||
Directory |
||||
} |
||||
} |
@ -1,159 +0,0 @@
@@ -1,159 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Diagnostics; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class Search |
||||
{ |
||||
ISearchStrategy searchStrategy = null; |
||||
IDocumentIterator documentIterator = null; |
||||
ITextIterator textIterator = null; |
||||
ITextIteratorBuilder textIteratorBuilder = null; |
||||
ProvidedDocumentInformation info = null; |
||||
|
||||
public ProvidedDocumentInformation CurrentDocumentInformation { |
||||
get { |
||||
return info; |
||||
} |
||||
} |
||||
|
||||
public ITextIteratorBuilder TextIteratorBuilder { |
||||
get { |
||||
return textIteratorBuilder; |
||||
} |
||||
set { |
||||
textIteratorBuilder = value; |
||||
} |
||||
} |
||||
|
||||
public ITextIterator TextIterator { |
||||
get { |
||||
return textIterator; |
||||
} |
||||
} |
||||
|
||||
public ISearchStrategy SearchStrategy { |
||||
get { |
||||
return searchStrategy; |
||||
} |
||||
set { |
||||
searchStrategy = value; |
||||
} |
||||
} |
||||
|
||||
public IDocumentIterator DocumentIterator { |
||||
get { |
||||
return documentIterator; |
||||
} |
||||
set { |
||||
documentIterator = value; |
||||
} |
||||
} |
||||
|
||||
SearchResultMatch CreateNamedSearchResult(SearchResultMatch pos) |
||||
{ |
||||
if (info == null || pos == null) { |
||||
return null; |
||||
} |
||||
pos.ProvidedDocumentInformation = info; |
||||
return pos; |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
documentIterator.Reset(); |
||||
textIterator = null; |
||||
} |
||||
|
||||
public void Replace(int offset, int length, string pattern) |
||||
{ |
||||
if (CurrentDocumentInformation != null && TextIterator != null) { |
||||
CurrentDocumentInformation.Replace(offset, length, pattern); |
||||
TextIterator.InformReplace(offset, length, pattern.Length); |
||||
} |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(IProgressMonitor monitor) |
||||
{ |
||||
// insanity check
|
||||
Debug.Assert(searchStrategy != null); |
||||
Debug.Assert(documentIterator != null); |
||||
Debug.Assert(textIteratorBuilder != null); |
||||
|
||||
if (monitor != null && monitor.CancellationToken.IsCancellationRequested) |
||||
return null; |
||||
|
||||
if (info != null && textIterator != null && documentIterator.CurrentFileName != null) { |
||||
ProvidedDocumentInformation currentInfo = documentIterator.Current; |
||||
if (currentInfo != null) { |
||||
if (!info.Equals(currentInfo)) { // create new iterator, if document changed
|
||||
info = currentInfo; |
||||
textIterator = textIteratorBuilder.BuildTextIterator(info); |
||||
} else { // old document -> initialize iterator position to caret pos
|
||||
textIterator.Position = info.CurrentOffset; |
||||
} |
||||
|
||||
SearchResultMatch result = CreateNamedSearchResult(searchStrategy.FindNext(textIterator)); |
||||
if (result != null) { |
||||
info.CurrentOffset = textIterator.Position; |
||||
return result; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// not found or first start -> move forward to the next document
|
||||
if (documentIterator.MoveForward()) { |
||||
info = documentIterator.Current; |
||||
// document is valid for searching -> set iterator & fileName
|
||||
if (info != null && info.EndOffset >= 0 && info.EndOffset <= info.Document.TextLength) { |
||||
textIterator = textIteratorBuilder.BuildTextIterator(info); |
||||
} else { |
||||
textIterator = null; |
||||
} |
||||
|
||||
return FindNext(monitor); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(int offset, int length) |
||||
{ |
||||
if (info != null && textIterator != null && documentIterator.CurrentFileName != null) { |
||||
ProvidedDocumentInformation currentInfo = documentIterator.Current; |
||||
if (currentInfo != null) { |
||||
if (!info.Equals(currentInfo)) { // create new iterator, if document changed
|
||||
info = currentInfo; |
||||
textIterator = textIteratorBuilder.BuildTextIterator(info); |
||||
} else { // old document -> initialize iterator position to caret pos
|
||||
textIterator.Position = info.CurrentOffset; |
||||
} |
||||
|
||||
SearchResultMatch result = CreateNamedSearchResult(searchStrategy.FindNext(textIterator, offset, length)); |
||||
if (result != null) { |
||||
info.CurrentOffset = textIterator.Position; |
||||
return result; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// not found or first start -> move forward to the next document
|
||||
if (documentIterator.MoveForward()) { |
||||
info = documentIterator.Current; |
||||
// document is valid for searching -> set iterator & fileName
|
||||
if (info != null && info.EndOffset >= 0 && info.EndOffset <= info.Document.TextLength) { |
||||
textIterator = textIteratorBuilder.BuildTextIterator(info); |
||||
} else { |
||||
textIterator = null; |
||||
} |
||||
|
||||
return FindNext(offset, length); |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,132 @@
@@ -0,0 +1,132 @@
|
||||
/* |
||||
* Created by SharpDevelop. |
||||
* User: Siegfried |
||||
* Date: 06.10.2011 |
||||
* Time: 21:33 |
||||
* |
||||
* To change this template use Tools | Options | Coding | Edit Standard Headers. |
||||
*/ |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Search; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// Description of SearchManager.
|
||||
/// </summary>
|
||||
public class SearchManager |
||||
{ |
||||
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; |
||||
foreach (var name in FileUtility.SearchDirectory(baseDirectory, filter, searchSubdirs)) |
||||
files.Add(new FileName(name)); |
||||
break; |
||||
default: |
||||
throw new Exception("Invalid value for FileListType"); |
||||
} |
||||
|
||||
return files.Distinct(); |
||||
} |
||||
|
||||
public static IObservable<SearchResultMatch> FindAll(string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, |
||||
SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false) |
||||
{ |
||||
CancellationTokenSource cts = new CancellationTokenSource(); |
||||
var monitor = WorkbenchSingleton.Workbench.StatusBar.CreateProgressMonitor(cts.Token); |
||||
monitor.TaskName = "Find All"; |
||||
monitor.Status = OperationStatus.Normal; |
||||
var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode); |
||||
ParseableFileContentFinder fileFinder = new ParseableFileContentFinder(); |
||||
var fileList = GenerateFileList(target, baseDirectory, filter, searchSubdirs); |
||||
return new SearchRun(strategy, fileFinder, fileList, monitor, cts); |
||||
} |
||||
|
||||
class SearchRun : IObservable<SearchResultMatch>, IDisposable |
||||
{ |
||||
IObserver<SearchResultMatch> observer; |
||||
ISearchStrategy strategy; |
||||
ParseableFileContentFinder fileFinder; |
||||
IEnumerable<FileName> fileList; |
||||
IProgressMonitor monitor; |
||||
CancellationTokenSource cts; |
||||
|
||||
public SearchRun(ISearchStrategy strategy, ParseableFileContentFinder fileFinder, IEnumerable<FileName> fileList, IProgressMonitor monitor, CancellationTokenSource cts) |
||||
{ |
||||
this.strategy = strategy; |
||||
this.fileFinder = fileFinder; |
||||
this.fileList = fileList; |
||||
this.monitor = monitor; |
||||
this.cts = cts; |
||||
} |
||||
|
||||
public IDisposable Subscribe(IObserver<SearchResultMatch> observer) |
||||
{ |
||||
this.observer = observer; |
||||
new System.Threading.Tasks.Task(delegate { Parallel.ForEach(fileList, fileName => SearchFile(fileFinder.Create(fileName).CreateSnapshot(), strategy, monitor.CancellationToken)); }).Start(); |
||||
return this; |
||||
} |
||||
|
||||
public void Dispose() |
||||
{ |
||||
if (!cts.IsCancellationRequested) |
||||
cts.Cancel(); |
||||
monitor.Dispose(); |
||||
} |
||||
|
||||
void SearchFile(ITextBuffer buffer, ISearchStrategy strategy, CancellationToken ct) |
||||
{ |
||||
if (!MimeTypeDetection.FindMimeType(buffer).StartsWith("text/")) |
||||
return; |
||||
var source = DocumentUtilitites.GetTextSource(buffer); |
||||
foreach(var result in strategy.FindAll(source)) { |
||||
ct.ThrowIfCancellationRequested(); |
||||
observer.OnNext(new SearchResultMatch(result.Offset, result.Length)); |
||||
} |
||||
lock (monitor) |
||||
monitor.Progress += 1 / fileList.Count(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public static class SearchInFilesManager |
||||
{ |
||||
static Search find = new Search(); |
||||
|
||||
static string currentFileName = String.Empty; |
||||
|
||||
static SearchInFilesManager() |
||||
{ |
||||
find.TextIteratorBuilder = new ForwardTextIteratorBuilder(); |
||||
} |
||||
|
||||
static void SetSearchOptions(IProgressMonitor monitor) |
||||
{ |
||||
find.SearchStrategy = SearchReplaceUtilities.CreateSearchStrategy(SearchOptions.SearchStrategyType); |
||||
find.DocumentIterator = SearchReplaceUtilities.CreateDocumentIterator(SearchOptions.DocumentIteratorType, monitor); |
||||
} |
||||
|
||||
static bool InitializeSearchInFiles(IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
|
||||
find.Reset(); |
||||
if (!find.SearchStrategy.CompilePattern(monitor)) |
||||
return false; |
||||
|
||||
currentFileName = String.Empty; |
||||
return true; |
||||
} |
||||
|
||||
static void FinishSearchInFiles(List<SearchResultMatch> results) |
||||
{ |
||||
ShowSearchResults(SearchOptions.FindPattern, results); |
||||
} |
||||
|
||||
public static void ShowSearchResults(string pattern, List<SearchResultMatch> results) |
||||
{ |
||||
string title = StringParser.Parse("${res:MainWindow.Windows.SearchResultPanel.OccurrencesOf}", |
||||
new StringTagPair("Pattern", pattern)); |
||||
SearchResultsPad.Instance.ShowSearchResults(title, results); |
||||
SearchResultsPad.Instance.BringToFront(); |
||||
} |
||||
|
||||
public static void FindAll(IProgressMonitor monitor) |
||||
{ |
||||
if (!InitializeSearchInFiles(monitor)) { |
||||
return; |
||||
} |
||||
|
||||
List<SearchResultMatch> results = new List<SearchResultMatch>(); |
||||
while (true) { |
||||
SearchResultMatch result = find.FindNext(monitor); |
||||
if (result == null) { |
||||
break; |
||||
} |
||||
results.Add(result); |
||||
} |
||||
FinishSearchInFiles(results); |
||||
} |
||||
|
||||
public static void FindAll(int offset, int length, IProgressMonitor monitor) |
||||
{ |
||||
if (!InitializeSearchInFiles(monitor)) { |
||||
return; |
||||
} |
||||
|
||||
List<SearchResultMatch> results = new List<SearchResultMatch>(); |
||||
while (true) { |
||||
SearchResultMatch result = find.FindNext(offset, length); |
||||
if (result == null) { |
||||
break; |
||||
} |
||||
results.Add(result); |
||||
} |
||||
FinishSearchInFiles(results); |
||||
} |
||||
} |
||||
} |
@ -1,393 +0,0 @@
@@ -1,393 +0,0 @@
|
||||
// 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.Windows.Forms; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Bookmarks; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class SearchReplaceManager |
||||
{ |
||||
public static SearchAndReplaceDialog SearchAndReplaceDialog = null; |
||||
|
||||
static Search find = new Search(); |
||||
|
||||
static SearchReplaceManager() |
||||
{ |
||||
find.TextIteratorBuilder = new ForwardTextIteratorBuilder(); |
||||
} |
||||
|
||||
static void SetSearchOptions(IProgressMonitor monitor) |
||||
{ |
||||
find.SearchStrategy = SearchReplaceUtilities.CreateSearchStrategy(SearchOptions.SearchStrategyType); |
||||
find.DocumentIterator = SearchReplaceUtilities.CreateDocumentIterator(SearchOptions.DocumentIteratorType, monitor); |
||||
} |
||||
|
||||
public static void Replace(IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
if (lastResult != null) { |
||||
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
if (provider != null) { |
||||
ITextEditor textarea = provider.TextEditor; |
||||
|
||||
if (textarea.SelectionStart == lastResult.Offset |
||||
&& textarea.SelectionLength == lastResult.Length |
||||
&& lastResult.FileName == textarea.FileName) |
||||
{ |
||||
string replacePattern = lastResult.TransformReplacePattern(SearchOptions.ReplacePattern); |
||||
|
||||
using (textarea.Document.OpenUndoGroup()) { |
||||
textarea.Document.Replace(lastResult.Offset, lastResult.Length, replacePattern); |
||||
textarea.Select(lastResult.Offset + replacePattern.Length, 0); // clear selection and set caret position
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
FindNext(monitor); |
||||
} |
||||
|
||||
static TextSelection textSelection; |
||||
|
||||
public static void ReplaceFirstInSelection(int offset, int length, IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
FindFirstInSelection(offset, length, monitor); |
||||
} |
||||
|
||||
public static bool ReplaceNextInSelection(IProgressMonitor monitor) |
||||
{ |
||||
if (lastResult != null) { |
||||
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
if (provider != null) { |
||||
ITextEditor textarea = provider.TextEditor; |
||||
|
||||
if (textarea.SelectionStart == lastResult.Offset |
||||
&& textarea.SelectionLength == lastResult.Length |
||||
&& lastResult.FileName == textarea.FileName) |
||||
{ |
||||
string replacePattern = lastResult.TransformReplacePattern(SearchOptions.ReplacePattern); |
||||
|
||||
using (textarea.Document.OpenUndoGroup()) { |
||||
textarea.Document.Replace(lastResult.Offset, lastResult.Length, replacePattern); |
||||
textarea.Select(lastResult.Offset + replacePattern.Length, 0); // clear selection and set caret position
|
||||
} |
||||
|
||||
textSelection.Length -= lastResult.Length - replacePattern.Length; |
||||
} |
||||
} |
||||
} |
||||
return FindNextInSelection(monitor); |
||||
} |
||||
|
||||
public static void MarkAll(IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
ClearSelection(); |
||||
find.Reset(); |
||||
if (!find.SearchStrategy.CompilePattern(monitor)) |
||||
return; |
||||
List<ITextEditor> textAreas = new List<ITextEditor>(); |
||||
int count; |
||||
for (count = 0;; count++) { |
||||
SearchResultMatch result = SearchReplaceManager.find.FindNext(monitor); |
||||
|
||||
if (result == null) { |
||||
break; |
||||
} else { |
||||
MarkResult(textAreas, result); |
||||
} |
||||
} |
||||
find.Reset(); |
||||
ShowMarkDoneMessage(count, monitor); |
||||
} |
||||
|
||||
public static void MarkAll(int offset, int length, IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
find.Reset(); |
||||
|
||||
if (!find.SearchStrategy.CompilePattern(monitor)) |
||||
return; |
||||
|
||||
List<ITextEditor> textAreas = new List<ITextEditor>(); |
||||
int count; |
||||
for (count = 0;; count++) { |
||||
SearchResultMatch result = find.FindNext(offset, length); |
||||
if (result == null) { |
||||
break; |
||||
} else { |
||||
MarkResult(textAreas, result); |
||||
} |
||||
} |
||||
find.Reset(); |
||||
ShowMarkDoneMessage(count, monitor); |
||||
} |
||||
|
||||
static void MarkResult(List<ITextEditor> textAreas, SearchResultMatch result) |
||||
{ |
||||
ITextEditor textArea = OpenTextArea(result.FileName); |
||||
if (textArea != null) { |
||||
if (!textAreas.Contains(textArea)) { |
||||
textAreas.Add(textArea); |
||||
} |
||||
textArea.Caret.Offset = result.Offset; |
||||
IDocumentLine segment = textArea.Document.GetLineForOffset(result.Offset); |
||||
|
||||
int lineNr = segment.LineNumber; |
||||
|
||||
foreach (var bookmark in BookmarkManager.GetBookmarks(result.FileName)) { |
||||
if (bookmark.CanToggle && bookmark.LineNumber == lineNr) { |
||||
// bookmark or breakpoint already exists at that line
|
||||
return; |
||||
} |
||||
} |
||||
BookmarkManager.AddMark(new Bookmark(result.FileName, textArea.Document.OffsetToPosition(result.Offset))); |
||||
} |
||||
} |
||||
|
||||
static void ShowMarkDoneMessage(int count, IProgressMonitor monitor) |
||||
{ |
||||
if (count == 0) { |
||||
ShowNotFoundMessage(monitor); |
||||
} else { |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageService.ShowMessage(StringParser.Parse("${res:ICSharpCode.TextEditor.Document.SearchReplaceManager.MarkAllDone}",new StringTagPair("Count", count.ToString())), |
||||
"${res:Global.FinishedCaptionText}"); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
} |
||||
} |
||||
|
||||
static void ShowReplaceDoneMessage(int count, IProgressMonitor monitor) |
||||
{ |
||||
if (count == 0) { |
||||
ShowNotFoundMessage(monitor); |
||||
} else { |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageService.ShowMessage( |
||||
StringParser.Parse("${res:ICSharpCode.TextEditor.Document.SearchReplaceManager.ReplaceAllDone}", |
||||
new StringTagPair("Count", count.ToString())), |
||||
"${res:Global.FinishedCaptionText}"); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
} |
||||
} |
||||
|
||||
public static void ReplaceAll(IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
ClearSelection(); |
||||
find.Reset(); |
||||
if (!find.SearchStrategy.CompilePattern(monitor)) |
||||
return; |
||||
|
||||
List<ITextEditor> textAreas = new List<ITextEditor>(); |
||||
ITextEditor textArea = null; |
||||
for (int count = 0;; count++) { |
||||
SearchResultMatch result = SearchReplaceManager.find.FindNext(monitor); |
||||
|
||||
if (result == null) { |
||||
if (count != 0) { |
||||
foreach (ITextEditor ta in textAreas) { |
||||
ta.Document.EndUndoableAction(); |
||||
} |
||||
} |
||||
ShowReplaceDoneMessage(count, monitor); |
||||
find.Reset(); |
||||
return; |
||||
} else { |
||||
if (textArea == null || textArea.FileName != result.FileName) { |
||||
// we need to open another text area
|
||||
textArea = OpenTextArea(result.FileName); |
||||
if (textArea != null) { |
||||
if (!textAreas.Contains(textArea)) { |
||||
textArea.Document.StartUndoableAction(); |
||||
textArea.Select(textArea.SelectionStart, 0); |
||||
textAreas.Add(textArea); |
||||
} |
||||
} |
||||
} |
||||
if (textArea != null) { |
||||
string transformedPattern = result.TransformReplacePattern(SearchOptions.ReplacePattern); |
||||
find.Replace(result.Offset, result.Length, transformedPattern); |
||||
if (find.CurrentDocumentInformation.IsDocumentCreatedFromTextBuffer) { |
||||
textArea.Document.Replace(result.Offset, result.Length, transformedPattern); |
||||
} |
||||
} else { |
||||
count--; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void ReplaceAll(int offset, int length, IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
find.Reset(); |
||||
|
||||
if (!find.SearchStrategy.CompilePattern(monitor)) |
||||
return; |
||||
|
||||
for (int count = 0;; count++) { |
||||
SearchResultMatch result = find.FindNext(offset, length); |
||||
if (result == null) { |
||||
ShowReplaceDoneMessage(count, monitor); |
||||
return; |
||||
} |
||||
|
||||
string replacement = result.TransformReplacePattern(SearchOptions.ReplacePattern); |
||||
find.Replace(result.Offset, |
||||
result.Length, |
||||
replacement); |
||||
length -= result.Length - replacement.Length; |
||||
|
||||
// HACK - Move the cursor to the correct offset - the caret gets
|
||||
// moved before the replace range if we replace a string with a
|
||||
// single character. The ProvidedDocInfo.Replace method assumes that
|
||||
// the current offset is at the end of the found text which it is not.
|
||||
find.CurrentDocumentInformation.CurrentOffset = result.Offset + replacement.Length - 1; |
||||
} |
||||
} |
||||
|
||||
static SearchResultMatch lastResult = null; |
||||
|
||||
public static void FindNext(IProgressMonitor monitor) |
||||
{ |
||||
SetSearchOptions(monitor); |
||||
if (find == null || |
||||
SearchOptions.FindPattern == null || |
||||
SearchOptions.FindPattern.Length == 0) { |
||||
return; |
||||
} |
||||
|
||||
if (!find.SearchStrategy.CompilePattern(monitor)) { |
||||
find.Reset(); |
||||
lastResult = null; |
||||
return; |
||||
} |
||||
|
||||
ITextEditor textArea = null; |
||||
while (textArea == null) { |
||||
SearchResultMatch result = find.FindNext(monitor); |
||||
if (result == null) { |
||||
ShowNotFoundMessage(monitor); |
||||
find.Reset(); |
||||
lastResult = null; |
||||
return; |
||||
} else { |
||||
textArea = OpenTextArea(result.FileName); |
||||
if (textArea != null) { |
||||
if (lastResult != null && lastResult.FileName == result.FileName && |
||||
textArea.Caret.Offset != lastResult.Offset + lastResult.Length) { |
||||
find.Reset(); |
||||
} |
||||
int startPos = Math.Min(textArea.Document.TextLength, Math.Max(0, result.Offset)); |
||||
int endPos = Math.Min(textArea.Document.TextLength, startPos + result.Length); |
||||
|
||||
textArea.Select(startPos, endPos - startPos); |
||||
lastResult = result; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
static bool foundAtLeastOneItem = false; |
||||
|
||||
public static void FindFirstInSelection(int offset, int length, IProgressMonitor monitor) |
||||
{ |
||||
foundAtLeastOneItem = false; |
||||
textSelection = null; |
||||
SetSearchOptions(monitor); |
||||
|
||||
if (find == null || |
||||
SearchOptions.FindPattern == null || |
||||
SearchOptions.FindPattern.Length == 0) { |
||||
return; |
||||
} |
||||
|
||||
if (!find.SearchStrategy.CompilePattern(monitor)) { |
||||
find.Reset(); |
||||
lastResult = null; |
||||
return; |
||||
} |
||||
|
||||
textSelection = new TextSelection(offset, length); |
||||
FindNextInSelection(monitor); |
||||
} |
||||
|
||||
public static bool FindNextInSelection(IProgressMonitor monitor) |
||||
{ |
||||
ITextEditor textArea = null; |
||||
while (textArea == null) { |
||||
SearchResultMatch result = find.FindNext(textSelection.Offset, textSelection.Length); |
||||
if (result == null) { |
||||
if (!foundAtLeastOneItem) { |
||||
ShowNotFoundMessage(monitor); |
||||
} |
||||
find.Reset(); |
||||
lastResult = null; |
||||
foundAtLeastOneItem = false; |
||||
return false; |
||||
} else { |
||||
textArea = OpenTextArea(result.FileName); |
||||
if (textArea != null) { |
||||
foundAtLeastOneItem = true; |
||||
if (lastResult != null && lastResult.FileName == result.FileName && |
||||
textArea.Caret.Offset != lastResult.Offset + lastResult.Length) { |
||||
} |
||||
int startPos = Math.Min(textArea.Document.TextLength, Math.Max(0, result.Offset)); |
||||
int endPos = Math.Min(textArea.Document.TextLength, startPos + result.Length); |
||||
textArea.Select(startPos, endPos - startPos); |
||||
lastResult = result; |
||||
} |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static void ShowNotFoundMessage(IProgressMonitor monitor) |
||||
{ |
||||
if (monitor != null && monitor.CancellationToken.IsCancellationRequested) |
||||
return; |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageBox.Show(WorkbenchSingleton.MainWin32Window, |
||||
ResourceService.GetString("Dialog.NewProject.SearchReplace.SearchStringNotFound"), |
||||
ResourceService.GetString("Dialog.NewProject.SearchReplace.SearchStringNotFound.Title"), |
||||
MessageBoxButtons.OK, |
||||
MessageBoxIcon.Information); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
} |
||||
|
||||
static ITextEditor OpenTextArea(string fileName) |
||||
{ |
||||
ITextEditorProvider textEditorProvider; |
||||
if (fileName != null) { |
||||
textEditorProvider = FileService.OpenFile(fileName) as ITextEditorProvider; |
||||
} else { |
||||
textEditorProvider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
} |
||||
|
||||
if (textEditorProvider != null) { |
||||
return textEditorProvider.TextEditor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
static void ClearSelection() |
||||
{ |
||||
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
if (provider != null) { |
||||
ITextEditor editor = provider.TextEditor; |
||||
if (editor.SelectionLength > 0) |
||||
editor.Select(editor.Caret.Offset, 0); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,112 +0,0 @@
@@ -1,112 +0,0 @@
|
||||
// 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; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public sealed class SearchReplaceUtilities |
||||
{ |
||||
public static bool IsTextAreaSelected { |
||||
get { |
||||
return WorkbenchSingleton.Workbench.ActiveViewContent is ITextEditorProvider; |
||||
} |
||||
} |
||||
|
||||
public static ITextEditor GetActiveTextEditor() |
||||
{ |
||||
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
if (provider != null) { |
||||
return provider.TextEditor; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
static bool IsWordPart(char c) |
||||
{ |
||||
return char.IsLetterOrDigit(c) || c == '_'; |
||||
} |
||||
|
||||
public static bool IsWholeWordAt(IDocument document, int offset, int length) |
||||
{ |
||||
return (offset - 1 < 0 || !IsWordPart(document.GetCharAt(offset - 1))) && |
||||
(offset + length + 1 >= document.TextLength || !IsWordPart(document.GetCharAt(offset + length))); |
||||
} |
||||
|
||||
public static ISearchStrategy CreateSearchStrategy(SearchStrategyType type) |
||||
{ |
||||
switch (type) { |
||||
case SearchStrategyType.Normal: |
||||
return new BruteForceSearchStrategy(); // new KMPSearchStrategy();
|
||||
case SearchStrategyType.RegEx: |
||||
return new RegExSearchStrategy(); |
||||
case SearchStrategyType.Wildcard: |
||||
return new WildcardSearchStrategy(); |
||||
default: |
||||
throw new System.NotImplementedException("CreateSearchStrategy for type " + type); |
||||
} |
||||
} |
||||
|
||||
public static IDocumentIterator CreateDocumentIterator(DocumentIteratorType type, IProgressMonitor monitor) |
||||
{ |
||||
switch (type) { |
||||
case DocumentIteratorType.CurrentDocument: |
||||
case DocumentIteratorType.CurrentSelection: |
||||
return new CurrentDocumentIterator(); |
||||
case DocumentIteratorType.Directory: |
||||
try { |
||||
if (!Directory.Exists(SearchOptions.LookIn)) { |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageService.ShowMessageFormatted("${res:Dialog.NewProject.SearchReplace.SearchStringNotFound.Title}", "${res:Dialog.NewProject.SearchReplace.LookIn.DirectoryNotFound}", FileUtility.NormalizePath(SearchOptions.LookIn)); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
return new DummyDocumentIterator(); |
||||
} |
||||
} catch (Exception ex) { |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageService.ShowMessage(ex.Message); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
return new DummyDocumentIterator(); |
||||
} |
||||
return new DirectoryDocumentIterator(SearchOptions.LookIn, |
||||
SearchOptions.LookInFiletypes, |
||||
SearchOptions.IncludeSubdirectories); |
||||
case DocumentIteratorType.AllOpenFiles: |
||||
return new AllOpenDocumentIterator(); |
||||
case DocumentIteratorType.WholeProject: |
||||
return new WholeProjectDocumentIterator(); |
||||
case DocumentIteratorType.WholeSolution: |
||||
return new WholeSolutionDocumentIterator(); |
||||
default: |
||||
throw new System.NotImplementedException("CreateDocumentIterator for type " + type); |
||||
} |
||||
} |
||||
|
||||
public static bool IsSearchable(string fileName) |
||||
{ |
||||
const int BUFFER_LENGTH = 4 * 1024; |
||||
|
||||
if (!File.Exists(fileName)) |
||||
return false; |
||||
|
||||
using (var stream = File.OpenRead(fileName)) { |
||||
string mime = "text/plain"; |
||||
if (stream.Length > 0) { |
||||
stream.Position = 0; |
||||
mime = MimeTypeDetection.FindMimeType(new BinaryReader(stream).ReadBytes(BUFFER_LENGTH)); |
||||
} |
||||
|
||||
return mime.StartsWith("text/", StringComparison.OrdinalIgnoreCase); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,128 +0,0 @@
@@ -1,128 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// This interface is the basic interface which all
|
||||
/// search algorithms must implement.
|
||||
/// </summary>
|
||||
public class BoyerMooreSearchStrategy |
||||
{ |
||||
// Shift table for chars present in the pattern
|
||||
Dictionary<char, int[]> patternCharShifts; |
||||
// Shifts for all other chars
|
||||
int[] otherCharShifts; |
||||
// the patern to search
|
||||
string searchPattern; |
||||
// Length of the search pattern
|
||||
int patternLength; |
||||
|
||||
/// <remarks>
|
||||
/// Only with a call to this method the search strategy must
|
||||
/// update their pattern information. This method will be called
|
||||
/// before the FindNext function.
|
||||
/// </remarks>
|
||||
public void CompilePattern() |
||||
{ |
||||
searchPattern = SearchOptions.MatchCase ? SearchOptions.FindPattern : SearchOptions.FindPattern.ToUpper(); |
||||
|
||||
// Building shift table
|
||||
patternLength = searchPattern.Length; |
||||
int maxShift = patternLength; |
||||
patternCharShifts = new Dictionary<char, int[]>(); |
||||
// Constructing the table where number
|
||||
// of columns is equal to PatternLength
|
||||
// and number of rows is equal to the
|
||||
// number of distinct chars in the pattern
|
||||
for (int i = 0; i < patternLength; ++i) { |
||||
if (!patternCharShifts.ContainsKey(searchPattern[i])) { |
||||
patternCharShifts.Add(searchPattern[i], new int[patternLength]); |
||||
} |
||||
} |
||||
otherCharShifts = new int[patternLength]; |
||||
// Filling the last column of the
|
||||
// table with maximum shifts (pattern length)
|
||||
foreach(KeyValuePair<char, int[]> row in patternCharShifts) { |
||||
row.Value[patternLength - 1] = maxShift; |
||||
} |
||||
otherCharShifts[patternLength - 1] = maxShift; |
||||
// Calculating other shifts (filling each column
|
||||
// from PatternLength - 2 to 0 (from right to left)
|
||||
for (int i = patternLength - 1; i >= 0; --i) |
||||
{ |
||||
// Suffix string contains the characters
|
||||
// right to the character being processsed
|
||||
string suffix = new String(searchPattern.ToCharArray(), |
||||
i + 1, patternLength - i - 1); |
||||
// if Pattern begins with Suffix
|
||||
// the maximum shift is equal to i + 1
|
||||
if (searchPattern.StartsWith(suffix)) { |
||||
maxShift = i + 1; |
||||
} |
||||
// Store shift for characters not present in the pattern
|
||||
otherCharShifts[i] = maxShift; |
||||
// We shorten patter by one char in NewPattern.
|
||||
string newPattern = new string(searchPattern.ToCharArray(), |
||||
0, searchPattern.Length -1); |
||||
if ((newPattern.LastIndexOf(suffix) > 0) || (suffix.Length == 0)) { |
||||
foreach(KeyValuePair<char, int[]> row in patternCharShifts) |
||||
{ |
||||
string newSuffix = row.Key + suffix; |
||||
// Calculate shifts:
|
||||
//Check if there are other occurences
|
||||
//of the new suffix in the pattern
|
||||
// If several occurences exist, we need the rightmost one
|
||||
int newSuffixPos = newPattern.LastIndexOf(newSuffix); |
||||
if (newSuffixPos >= 0) { |
||||
row.Value[i] = i - newSuffixPos; |
||||
} else { |
||||
row.Value[i] = maxShift; |
||||
} |
||||
// Storing 0 if characters
|
||||
// in a row and a columnt are the same
|
||||
if (row.Key == searchPattern[i]) { |
||||
row.Value[i] = 0; |
||||
} |
||||
} |
||||
} else { |
||||
foreach(KeyValuePair<char, int[]> row in patternCharShifts) |
||||
{ |
||||
// if Suffix doesn't occure in NewPattern
|
||||
// we simply use previous shift value
|
||||
row.Value[i] = maxShift; |
||||
if (row.Key == searchPattern[i]) { |
||||
row.Value[i] = 0; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
int InternalFindNext(ITextIterator textIterator) |
||||
{ |
||||
// while (textIterator.MoveAhead(1)) {
|
||||
// if (SearchOptions.MatchCase ? MatchCaseSensitive(textIterator.TextBuffer, textIterator.Position, searchPattern) : MatchCaseInsensitive(textIterator.TextBuffer, textIterator.Position, searchPattern)) {
|
||||
// if (!SearchOptions.MatchWholeWord || IsWholeWordAt(textIterator.TextBuffer, textIterator.Position, searchPattern.Length)) {
|
||||
// return textIterator.Position;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return -1; |
||||
} |
||||
|
||||
/// <remarks>
|
||||
/// The find next method should search the next occurrence of the
|
||||
/// compiled pattern in the text using the textIterator and options.
|
||||
/// </remarks>
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator) |
||||
{ |
||||
int offset = InternalFindNext(textIterator); |
||||
return offset >= 0 ? new SearchResultMatch(offset, searchPattern.Length) : null; |
||||
} |
||||
} |
||||
} |
@ -1,91 +0,0 @@
@@ -1,91 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// Only for fallback purposes.
|
||||
/// </summary>
|
||||
public class BruteForceSearchStrategy : ISearchStrategy |
||||
{ |
||||
string searchPattern; |
||||
|
||||
bool MatchCaseSensitive(IDocument document, int offset, string pattern) |
||||
{ |
||||
for (int i = 0; i < pattern.Length; ++i) { |
||||
if (offset + i >= document.TextLength || document.GetCharAt(offset + i) != pattern[i]) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
bool MatchCaseInsensitive(IDocument document, int offset, string pattern) |
||||
{ |
||||
for (int i = 0; i < pattern.Length; ++i) { |
||||
if (offset + i >= document.TextLength || Char.ToUpper(document.GetCharAt(offset + i)) != pattern[i]) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
int InternalFindNext(ITextIterator textIterator) |
||||
{ |
||||
while (textIterator.MoveAhead(1)) { |
||||
if (SearchOptions.MatchCase ? MatchCaseSensitive(textIterator.Document, textIterator.Position, searchPattern) : MatchCaseInsensitive(textIterator.Document, textIterator.Position, searchPattern)) { |
||||
if (!SearchOptions.MatchWholeWord || SearchReplaceUtilities.IsWholeWordAt(textIterator.Document, textIterator.Position, searchPattern.Length)) { |
||||
return textIterator.Position; |
||||
} |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
int InternalFindNext(ITextIterator textIterator, int offset, int length) |
||||
{ |
||||
while (textIterator.MoveAhead(1)) { |
||||
if (textIterator.Position >= offset + length) { |
||||
textIterator.Position = offset; |
||||
} |
||||
if (SearchOptions.MatchCase ? MatchCaseSensitive(textIterator.Document, textIterator.Position, searchPattern) : MatchCaseInsensitive(textIterator.Document, textIterator.Position, searchPattern)) { |
||||
if (!SearchOptions.MatchWholeWord || SearchReplaceUtilities.IsWholeWordAt(textIterator.Document, textIterator.Position, searchPattern.Length)) { |
||||
if (TextSelection.IsInsideRange(textIterator.Position + searchPattern.Length - 1, offset, length)) { |
||||
return textIterator.Position; |
||||
} else { |
||||
return -1; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
public bool CompilePattern(ICSharpCode.SharpDevelop.Gui.IProgressMonitor monitor) |
||||
{ |
||||
searchPattern = SearchOptions.MatchCase ? SearchOptions.FindPattern : SearchOptions.FindPattern.ToUpper(); |
||||
return true; |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator) |
||||
{ |
||||
int offset = InternalFindNext(textIterator); |
||||
return GetSearchResult(offset); |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator, int offset, int length) |
||||
{ |
||||
int foundOffset = InternalFindNext(textIterator, offset, length); |
||||
return GetSearchResult(foundOffset); |
||||
} |
||||
|
||||
SearchResultMatch GetSearchResult(int offset) |
||||
{ |
||||
return offset >= 0 ? new SearchResultMatch(offset, searchPattern.Length) : null; |
||||
} |
||||
} |
||||
} |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// This interface is the basic interface which all
|
||||
/// search algorithms must implement.
|
||||
/// </summary>
|
||||
public interface ISearchStrategy |
||||
{ |
||||
/// <remarks>
|
||||
/// Only with a call to this method the search strategy must
|
||||
/// update their pattern information. This method will be called
|
||||
/// before the FindNext function.
|
||||
/// The method might show a message box to the user if the pattern is invalid.
|
||||
/// </remarks>
|
||||
bool CompilePattern(IProgressMonitor monitor); |
||||
|
||||
/// <remarks>
|
||||
/// The find next method should search the next occurrence of the
|
||||
/// compiled pattern in the text using the textIterator and options.
|
||||
/// </remarks>
|
||||
SearchResultMatch FindNext(ITextIterator textIterator); |
||||
|
||||
/// <summary>
|
||||
/// Find only in the specified range.
|
||||
/// </summary>
|
||||
SearchResultMatch FindNext(ITextIterator textIterator, int offset, int length); |
||||
} |
||||
} |
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
//// <file>
|
||||
//// <copyright see="prj:///doc/copyright.txt"/>
|
||||
//// <license see="prj:///doc/license.txt"/>
|
||||
//// <owner name="Andrea Paatz" email="andrea@icsharpcode.net"/>
|
||||
//// <version value="$version"/>
|
||||
//// </file>
|
||||
//
|
||||
//using System;
|
||||
//
|
||||
//namespace SearchAndReplace
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// Implements the Knuth, Morris, Pratt searching algorithm.
|
||||
// /// </summary>
|
||||
// public class KMPSearchStrategy : ISearchStrategy
|
||||
// {
|
||||
// string searchPattern;
|
||||
// int[] overlap;
|
||||
//
|
||||
// public void CompilePattern()
|
||||
// {
|
||||
// if (searchPattern != (options.IgnoreCase ? options.SearchPattern.ToUpper() : options.SearchPattern)) {
|
||||
// searchPattern = options.IgnoreCase ? options.SearchPattern.ToUpper() : options.SearchPattern;
|
||||
// overlap = new int[searchPattern.Length + 1];
|
||||
// Preprocessing();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void Preprocessing()
|
||||
// {
|
||||
// overlap[0] = -1;
|
||||
// for (int i = 0, j = -1; i < searchPattern.Length;) {
|
||||
// while (j >= 0 && searchPattern[i] != searchPattern[j]) {
|
||||
// j = overlap[j];
|
||||
// }
|
||||
// ++i;
|
||||
// ++j;
|
||||
// overlap[i] = j;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int InternalFindNext(ITextIterator textIterator)
|
||||
// {
|
||||
// int j = 0;
|
||||
// if (!textIterator.MoveAhead(1)) {
|
||||
// return -1;
|
||||
// }
|
||||
// while (true) { // until pattern found or Iterator finished
|
||||
// while (j >= 0 && searchPattern[j] != (options.IgnoreCase ? Char.ToUpper(textIterator.GetCharRelative(j)) : textIterator.GetCharRelative(j))) {
|
||||
// if (!textIterator.MoveAhead(j - overlap[j])) {
|
||||
// return -1;
|
||||
// }
|
||||
// j = overlap[j];
|
||||
// }
|
||||
// if (++j >= searchPattern.Length) {
|
||||
// if ((!options.SearchWholeWordOnly || SearchReplaceUtilities.IsWholeWordAt(textIterator.TextBuffer, textIterator.Position, searchPattern.Length))) {
|
||||
// return textIterator.Position;
|
||||
// }
|
||||
// if (!textIterator.MoveAhead(j - overlap[j])) {
|
||||
// return -1;
|
||||
// }
|
||||
// j = overlap[j];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public SearchResult FindNext(ITextIterator textIterator)
|
||||
// {
|
||||
// int offset = InternalFindNext(textIterator, options);
|
||||
//
|
||||
// if (offset + searchPattern.Length >= textIterator.TextBuffer.Length) {
|
||||
// return FindNext(textIterator, options);
|
||||
// }
|
||||
//
|
||||
// return offset >= 0 ? new SearchResult(offset, searchPattern.Length) : null;
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -1,103 +0,0 @@
@@ -1,103 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Text.RegularExpressions; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class RegExSearchStrategy : ISearchStrategy |
||||
{ |
||||
Regex regex = null; |
||||
|
||||
public bool CompilePattern(IProgressMonitor monitor) |
||||
{ |
||||
RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Multiline; |
||||
if (!SearchOptions.MatchCase) { |
||||
regexOptions |= RegexOptions.IgnoreCase; |
||||
} |
||||
try { |
||||
regex = new Regex(SearchOptions.FindPattern, regexOptions); |
||||
return true; |
||||
} catch (ArgumentException ex) { |
||||
if (monitor != null) monitor.ShowingDialog = true; |
||||
MessageService.ShowError("${res:Dialog.NewProject.SearchReplace.ErrorParsingRegex}\n" + ex.Message); |
||||
if (monitor != null) monitor.ShowingDialog = false; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator) |
||||
{ |
||||
string document = textIterator.Document.Text; |
||||
|
||||
while (textIterator.MoveAhead(1)) { |
||||
Match m = regex.Match(document, textIterator.Position); |
||||
if (m == null || !m.Success) { |
||||
while (textIterator.Position < document.Length - 1) { |
||||
if (!textIterator.MoveAhead(1)) |
||||
return null; |
||||
} |
||||
} else { |
||||
int delta = m.Index - textIterator.Position; |
||||
if (delta <= 0 || textIterator.MoveAhead(delta)) { |
||||
return new RegexSearchResult(m); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator, int offset, int length) |
||||
{ |
||||
string document = textIterator.Document.GetText(0, textIterator.Document.TextLength); |
||||
|
||||
while (textIterator.MoveAhead(1)) { |
||||
if (textIterator.Position >= offset + length) { |
||||
textIterator.Position = offset; |
||||
} |
||||
Match m = regex.Match(document, textIterator.Position); |
||||
if (m == null || !m.Success) { |
||||
while (textIterator.Position < document.Length - 1) { |
||||
if (!textIterator.MoveAhead(1)) |
||||
return null; |
||||
} |
||||
} else { |
||||
int delta = m.Index - textIterator.Position; |
||||
if (delta <= 0 || textIterator.MoveAhead(delta)) { |
||||
if (TextSelection.IsInsideRange(m.Index + m.Length - 1, offset, length)) { |
||||
return new RegexSearchResult(m); |
||||
} else { |
||||
return null; |
||||
} |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
private sealed class RegexSearchResult : SearchResultMatch |
||||
{ |
||||
Match m; |
||||
|
||||
internal RegexSearchResult(Match m) : base(m.Index, m.Length) |
||||
{ |
||||
this.m = m; |
||||
} |
||||
|
||||
public override string TransformReplacePattern(string pattern) |
||||
{ |
||||
return m.Result(pattern); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,190 +0,0 @@
@@ -1,190 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Collections; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// Implements a wildcard search strategy.
|
||||
///
|
||||
/// Wildcard search has following pattern code :
|
||||
/// * = Zero or more of any character
|
||||
/// ? = Any single character
|
||||
/// # = Any single digit
|
||||
/// [...] = Any one character in the set
|
||||
/// [!...] = Any one character not in the set
|
||||
/// </summary>
|
||||
public class WildcardSearchStrategy : ISearchStrategy |
||||
{ |
||||
enum CommandType { |
||||
Match, |
||||
AnyZeroOrMore, |
||||
AnySingle, |
||||
AnyDigit, |
||||
AnyInList, |
||||
NoneInList |
||||
} |
||||
|
||||
class Command { |
||||
public CommandType CommandType = CommandType.Match; |
||||
public char SingleChar = '\0'; |
||||
public string CharList = String.Empty; |
||||
} |
||||
|
||||
ArrayList patternProgram = null; |
||||
int curMatchEndOffset = -1; |
||||
|
||||
void CompilePattern(string pattern, bool ignoreCase) |
||||
{ |
||||
patternProgram = new ArrayList(); |
||||
for (int i = 0; i < pattern.Length; ++i) { |
||||
Command newCommand = new Command(); |
||||
switch (pattern[i]) { |
||||
case '#': |
||||
newCommand.CommandType = CommandType.AnyDigit; |
||||
break; |
||||
case '*': |
||||
newCommand.CommandType = CommandType.AnyZeroOrMore; |
||||
break; |
||||
case '?': |
||||
newCommand.CommandType = CommandType.AnySingle; |
||||
break; |
||||
case '[': |
||||
int index = pattern.IndexOf(']', i); |
||||
if (index > 0) { |
||||
newCommand.CommandType = CommandType.AnyInList; |
||||
string list = pattern.Substring(i + 1, index - i - 1); |
||||
if (list[0] == '!') { |
||||
newCommand.CommandType = CommandType.NoneInList; |
||||
list = list.Substring(1); |
||||
} |
||||
newCommand.CharList = ignoreCase ? list.ToUpper() : list; |
||||
i = index; |
||||
} else { |
||||
goto default; |
||||
} |
||||
break; |
||||
default: |
||||
newCommand.CommandType = CommandType.Match; |
||||
newCommand.SingleChar = ignoreCase ? Char.ToUpper(pattern[i]) : pattern[i]; |
||||
break; |
||||
} |
||||
patternProgram.Add(newCommand); |
||||
} |
||||
} |
||||
|
||||
bool Match(IDocument document, |
||||
int offset, |
||||
bool ignoreCase, |
||||
int programStart) |
||||
{ |
||||
int curOffset = offset; |
||||
curMatchEndOffset = -1; |
||||
|
||||
for (int pc = programStart; pc < patternProgram.Count; ++pc) { |
||||
if (curOffset >= document.TextLength) { |
||||
return false; |
||||
} |
||||
|
||||
char ch = ignoreCase ? Char.ToUpper(document.GetCharAt(curOffset)) : document.GetCharAt(curOffset); |
||||
Command cmd = (Command)patternProgram[pc]; |
||||
|
||||
switch (cmd.CommandType) { |
||||
case CommandType.Match: |
||||
if (ch != cmd.SingleChar) { |
||||
return false; |
||||
} |
||||
break; |
||||
case CommandType.AnyZeroOrMore: |
||||
if (ch == '\n') { |
||||
return false; |
||||
} |
||||
return Match(document, curOffset, ignoreCase, pc + 1) || |
||||
Match(document, curOffset + 1, ignoreCase, pc); |
||||
case CommandType.AnySingle: |
||||
break; |
||||
case CommandType.AnyDigit: |
||||
if (!Char.IsDigit(ch) && ch != '#') { |
||||
return false; |
||||
} |
||||
break; |
||||
case CommandType.AnyInList: |
||||
if (cmd.CharList.IndexOf(ch) < 0) { |
||||
return false; |
||||
} |
||||
break; |
||||
case CommandType.NoneInList: |
||||
if (cmd.CharList.IndexOf(ch) >= 0) { |
||||
return false; |
||||
} |
||||
break; |
||||
} |
||||
++curOffset; |
||||
} |
||||
curMatchEndOffset = curOffset; |
||||
return true; |
||||
} |
||||
|
||||
int InternalFindNext(ITextIterator textIterator) |
||||
{ |
||||
while (textIterator.MoveAhead(1)) { |
||||
int position = textIterator.Position; |
||||
if (Match(textIterator.Document, position, !SearchOptions.MatchCase, 0)) { |
||||
if (!SearchOptions.MatchWholeWord || SearchReplaceUtilities.IsWholeWordAt(textIterator.Document, position, curMatchEndOffset - position)) { |
||||
textIterator.MoveAhead(curMatchEndOffset - position - 1); |
||||
return position; |
||||
} |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
int InternalFindNext(ITextIterator textIterator, int offset, int length) |
||||
{ |
||||
while (textIterator.MoveAhead(1)) { |
||||
if (textIterator.Position >= offset + length) { |
||||
textIterator.Position = offset; |
||||
} |
||||
int position = textIterator.Position; |
||||
if (Match(textIterator.Document, position, !SearchOptions.MatchCase, 0)) { |
||||
if (!SearchOptions.MatchWholeWord || SearchReplaceUtilities.IsWholeWordAt(textIterator.Document, position, curMatchEndOffset - position)) { |
||||
if (TextSelection.IsInsideRange(curMatchEndOffset - 1, offset, length)) { |
||||
textIterator.MoveAhead(curMatchEndOffset - position - 1); |
||||
return position; |
||||
} else { |
||||
return -1; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
public bool CompilePattern(ICSharpCode.SharpDevelop.Gui.IProgressMonitor monitor) |
||||
{ |
||||
CompilePattern(SearchOptions.FindPattern, !SearchOptions.MatchCase); |
||||
return true; |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator) |
||||
{ |
||||
int offset = InternalFindNext(textIterator); |
||||
return GetSearchResult(offset); |
||||
} |
||||
|
||||
public SearchResultMatch FindNext(ITextIterator textIterator, int offset, int length) |
||||
{ |
||||
int foundOffset = InternalFindNext(textIterator, offset, length); |
||||
return GetSearchResult(foundOffset); |
||||
} |
||||
|
||||
SearchResultMatch GetSearchResult(int offset) |
||||
{ |
||||
return offset >= 0 ? new SearchResultMatch(offset, curMatchEndOffset - offset) : null; |
||||
} |
||||
} |
||||
} |
@ -1,163 +0,0 @@
@@ -1,163 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Diagnostics; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class ForwardTextIterator : ITextIterator |
||||
{ |
||||
ProvidedDocumentInformation info; |
||||
|
||||
enum TextIteratorState { |
||||
Resetted, |
||||
Iterating, |
||||
Done, |
||||
} |
||||
|
||||
TextIteratorState state; |
||||
|
||||
IDocument document; |
||||
int endOffset; |
||||
int oldOffset = -1; |
||||
|
||||
public IDocument Document { |
||||
get { |
||||
return document; |
||||
} |
||||
} |
||||
|
||||
public char Current { |
||||
get { |
||||
switch (state) { |
||||
case TextIteratorState.Resetted: |
||||
throw new System.InvalidOperationException("Call moveAhead first"); |
||||
case TextIteratorState.Iterating: |
||||
return document.GetCharAt(Position); |
||||
case TextIteratorState.Done: |
||||
throw new System.InvalidOperationException("TextIterator is at the end"); |
||||
default: |
||||
throw new System.InvalidOperationException("unknown text iterator state"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
int position; |
||||
public int Position { |
||||
get { |
||||
return position; |
||||
} |
||||
set { |
||||
position = value; |
||||
} |
||||
} |
||||
|
||||
public ForwardTextIterator(ProvidedDocumentInformation info) |
||||
{ |
||||
if (info == null) |
||||
throw new ArgumentNullException("info"); |
||||
|
||||
this.info = info; |
||||
this.document = info.Document; |
||||
this.position = info.CurrentOffset; |
||||
this.endOffset = info.EndOffset; |
||||
|
||||
Reset(); |
||||
} |
||||
|
||||
public char GetCharRelative(int offset) |
||||
{ |
||||
if (state != TextIteratorState.Iterating) { |
||||
throw new System.InvalidOperationException(); |
||||
} |
||||
|
||||
int realOffset = (Position + (1 + Math.Abs(offset) / document.TextLength) * document.TextLength + offset) % document.TextLength; |
||||
return document.GetCharAt(realOffset); |
||||
} |
||||
|
||||
public bool MoveAhead(int numChars) |
||||
{ |
||||
Debug.Assert(numChars > 0); |
||||
|
||||
// HACK : ignore files with length 1 (fixes SD-1815)
|
||||
if (document.TextLength == 1) { |
||||
state = TextIteratorState.Done; |
||||
return false; |
||||
} |
||||
|
||||
switch (state) { |
||||
case TextIteratorState.Resetted: |
||||
if (document.TextLength == 0) { |
||||
state = TextIteratorState.Done; |
||||
return false; |
||||
} |
||||
Position = endOffset; |
||||
state = TextIteratorState.Iterating; |
||||
return true; |
||||
case TextIteratorState.Done: |
||||
return false; |
||||
case TextIteratorState.Iterating: |
||||
if (oldOffset == -1 && document.TextLength == endOffset) { |
||||
// HACK: Take off one if the iterator start
|
||||
// position is at the end of the text.
|
||||
Position--; |
||||
} |
||||
|
||||
if (oldOffset != -1 && Position == endOffset - 1 && document.TextLength == endOffset) { |
||||
state = TextIteratorState.Done; |
||||
return false; |
||||
} |
||||
|
||||
Position = (Position + numChars) % document.TextLength; |
||||
bool finish = oldOffset != -1 && (oldOffset > Position || oldOffset < endOffset) && Position >= endOffset; |
||||
|
||||
// HACK: Iterating is complete if Position == endOffset - 1
|
||||
// when the iterator start position was initially at the
|
||||
// end of the text.
|
||||
if (oldOffset != -1 && oldOffset == endOffset - 1 && document.TextLength == endOffset) { |
||||
finish = true; |
||||
} |
||||
|
||||
oldOffset = Position; |
||||
if (finish) { |
||||
state = TextIteratorState.Done; |
||||
return false; |
||||
} |
||||
return true; |
||||
default: |
||||
throw new Exception("Unknown text iterator state"); |
||||
} |
||||
} |
||||
|
||||
public void InformReplace(int offset, int length, int newLength) |
||||
{ |
||||
if (offset <= endOffset) { |
||||
endOffset = endOffset - length + newLength; |
||||
} |
||||
|
||||
if (offset <= Position) { |
||||
Position = Position - length + newLength; |
||||
} |
||||
|
||||
if (offset <= oldOffset) { |
||||
oldOffset = oldOffset - length + newLength; |
||||
} |
||||
} |
||||
|
||||
public void Reset() |
||||
{ |
||||
state = TextIteratorState.Resetted; |
||||
Position = endOffset; |
||||
oldOffset = -1; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return String.Format("[ForwardTextIterator: Position={0}, endOffset={1}, state={2}]", Position, endOffset, state); |
||||
} |
||||
} |
||||
} |
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor.Search; |
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class ForwardTextIteratorBuilder : ITextIteratorBuilder |
||||
{ |
||||
public ITextIterator BuildTextIterator(ProvidedDocumentInformation info) |
||||
{ |
||||
Debug.Assert(info != null); |
||||
return new ForwardTextIterator(info); |
||||
} |
||||
} |
||||
} |
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop.Editor; |
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
/// <summary>
|
||||
/// This iterator iterates on a text buffer strategy.
|
||||
/// </summary>
|
||||
public interface ITextIterator |
||||
{ |
||||
/// <value>
|
||||
/// The text buffer strategy
|
||||
/// </value>
|
||||
IDocument Document { |
||||
get; |
||||
} |
||||
|
||||
/// <value>
|
||||
/// Gets the current char this is the same as
|
||||
/// GetCharRelative(0)
|
||||
/// </value>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If this method is called before the first MoveAhead or after
|
||||
/// MoveAhead or after MoveAhead returns false.
|
||||
/// </exception>
|
||||
char Current { |
||||
get; |
||||
} |
||||
|
||||
/// <value>
|
||||
/// The current position=offset of the text iterator cursor
|
||||
/// </value>
|
||||
int Position { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
/// <remarks>
|
||||
/// Gets a char relative to the current position (negative values
|
||||
/// will work too).
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If this method is called before the first MoveAhead or after
|
||||
/// MoveAhead or after MoveAhead returns false.
|
||||
/// </exception>
|
||||
char GetCharRelative(int offset); |
||||
|
||||
/// <remarks>
|
||||
/// Moves the iterator position numChars
|
||||
/// </remarks>
|
||||
bool MoveAhead(int numChars); |
||||
|
||||
/// <remarks>
|
||||
/// Rests the iterator
|
||||
/// </remarks>
|
||||
void Reset(); |
||||
|
||||
/// <remarks>
|
||||
/// The find object calls the InformReplace method to inform the text iterator
|
||||
/// about the replace operation on the TextBuffer. The text iterator must update
|
||||
/// all internal offsets to the new offsets (if neccessary)
|
||||
/// </remarks>
|
||||
void InformReplace(int offset, int length, int newLength); |
||||
} |
||||
} |
@ -1,45 +0,0 @@
@@ -1,45 +0,0 @@
|
||||
// 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; |
||||
|
||||
namespace SearchAndReplace |
||||
{ |
||||
public class TextSelection |
||||
{ |
||||
int offset; |
||||
int length; |
||||
|
||||
public TextSelection(int offset, int length) |
||||
{ |
||||
this.offset = offset; |
||||
this.length = length; |
||||
} |
||||
|
||||
public int Length { |
||||
get { |
||||
return length; |
||||
} |
||||
set { |
||||
length = value; |
||||
} |
||||
} |
||||
|
||||
public int Offset { |
||||
get { |
||||
return offset; |
||||
} |
||||
set { |
||||
offset = value; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Checks whether a position is in a specified range.
|
||||
/// </summary>
|
||||
public static bool IsInsideRange(int position, int offset, int length) |
||||
{ |
||||
return position >= offset && position < offset + length; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue