Rubberduck's latest (and greatest?) feature is a regex search/replace:
This is the defining interface:
public interface IRegexSearchReplace
{
List<RegexSearchResult> Find(string pattern, RegexSearchReplaceScope scope = RegexSearchReplaceScope.CurrentFile);
void Replace(string searchPattern, string replaceValue, RegexSearchReplaceScope scope = RegexSearchReplaceScope.CurrentFile);
void ReplaceAll(string searchPattern, string replaceValue, RegexSearchReplaceScope scope = RegexSearchReplaceScope.CurrentFile);
}
And here is the implementation:
private readonly RegexSearchReplaceModel _model;
public RegexSearchReplace(RegexSearchReplaceModel model)
{
_model = model;
}
public List<RegexSearchResult> Find(string searchPattern, RegexSearchReplaceScope scope)
{
var results = new List<RegexSearchResult>();
switch (scope)
{
case RegexSearchReplaceScope.Selection:
results.AddRange(GetResultsFromModule(_model.VBE.ActiveCodePane.CodeModule, searchPattern));
results = results.Where(r => _model.Selection.Selection.Contains(r.Selection)).ToList();
break;
case RegexSearchReplaceScope.CurrentBlock:
var declarationTypes = new []
{
DeclarationType.Event,
DeclarationType.Function,
DeclarationType.Procedure,
DeclarationType.PropertyGet,
DeclarationType.PropertyLet,
DeclarationType.PropertySet
};
results.AddRange(GetResultsFromModule(_model.VBE.ActiveCodePane.CodeModule, searchPattern));
dynamic block = _model.ParseResult.Declarations.FindSelection(_model.Selection, declarationTypes).Context.Parent;
var selection = new Selection(block.Start.Line, block.Start.Column, block.Stop.Line,
block.Stop.Column);
results = results.Where(r => selection.Contains(r.Selection)).ToList();
break;
case RegexSearchReplaceScope.CurrentFile:
results.AddRange(GetResultsFromModule(_model.VBE.ActiveCodePane.CodeModule, searchPattern));
break;
case RegexSearchReplaceScope.AllOpenedFiles:
foreach (var codePane in _model.VBE.CodePanes.Cast<CodePane>().Where(codePane => ReferenceEquals(_model.VBE, codePane.VBE)))
{
results.AddRange(GetResultsFromModule(codePane.CodeModule, searchPattern));
}
break;
case RegexSearchReplaceScope.CurrentProject:
foreach (var component in _model.VBE.ActiveVBProject.VBComponents.Cast<VBComponent>())
{
var module = component.CodeModule;
if (!ReferenceEquals(_model.VBE.ActiveVBProject, module.VBE.ActiveVBProject)) { continue; }
results.AddRange(GetResultsFromModule(module, searchPattern));
}
break;
case RegexSearchReplaceScope.AllOpenProjects:
foreach (VBProject project in _model.VBE.VBProjects)
{
foreach (var component in project.VBComponents.Cast<VBComponent>())
{
var module = component.CodeModule;
if (!ReferenceEquals(_model.VBE, module.VBE))
{
continue;
}
results.AddRange(GetResultsFromModule(module, searchPattern));
}
}
break;
}
return results;
}
public void Replace(string searchPattern, string replaceValue, RegexSearchReplaceScope scope)
{
var results = Find(searchPattern, scope);
if (results.Count <= 0) { return; }
var originalLine = results[0].Module.Lines[results[0].Selection.StartLine, 1];
var newLine = originalLine.Replace(results[0].Match.Value, replaceValue);
results[0].Module.ReplaceLine(results[0].Selection.StartLine, newLine);
}
public void ReplaceAll(string searchPattern, string replaceValue, RegexSearchReplaceScope scope)
{
var results = Find(searchPattern, scope);
foreach (var result in results)
{
var originalLine = result.Module.Lines[result.Selection.StartLine, 1];
var newLine = originalLine.Replace(result.Match.Value, replaceValue);
result.Module.ReplaceLine(result.Selection.StartLine, newLine);
}
}
private IEnumerable<RegexSearchResult> GetResultsFromModule(CodeModule module, string searchPattern)
{
var results = new List<RegexSearchResult>();
for (var i = 1; i <= module.CountOfLines; i++)
{
var matches =
Regex.Matches(module.Lines[i, 1], searchPattern)
.OfType<Match>()
.Select(m => new RegexSearchResult(m, module, i)).ToList();
if (matches.Any())
{
results.AddRange(matches);
}
}
return results;
}
As always, any and all comments are welcome.
Replace ()
method, how shouldresults.Count
ever be < 0 ? – Heslacher Jul 29 at 15:49