Based on some of the feedback we got from our last blog post on find/replace functionality, we’ve implemented a new extensibility feature in SyntaxEditor for WPF: custom search pattern formats.
What is a search pattern format?
A search pattern format is a syntax for entering how to find and replace text within a document. SyntaxEditor for WPF ships with three built-in formats:
- Normal is a plain text find and replace format.
- Regular Expression use regular expressions to match find text, and uses regular expression replace pattern syntax to allow for replacements at different matched capture points in the find pattern.
- Wildcard uses simple wildcard search patterns to match text.
These three options are available from static properties on the SearchPatternProviders class. They all implement the ISearchPatternProvider interface.
How to use them?
All find/replace operations take an ISearchOptions instance. One of the properties on that interface is called PatternProvider. You can pass any instance of ISearchPatternProvider to that property to indicate how to interpret the find and replace patterns.
The find/replace UI control that was introduced in the previous post lets the end user choose which pattern provider to use.
Now for the neat part, you as a developer can make custom search pattern providers if you wish to support a custom pattern format. And the find/replace UI control can include your custom providers in the drop-down list.
Implementing a custom ISearchPatternProvider
The ISearchPatternProvider interface has several members. One is a string Key that identifies it. Another is a more verbose Description that can be displayed in user interfaces. Then there are two methods that must be implemented:
1: /// <summary>
2: /// Returns the regular expression match pattern to use for find operations,
3: /// based on the supplied pattern that uses this provider.
4: /// </summary>
5: /// <param name="pattern">The pattern to convert using this provider.</param>
6: /// <returns>The regular expression match pattern to use for
7: /// find operations.</returns>
8: string GetFindPattern(string pattern);
9:
10: /// <summary>
11: /// Returns the regular expression match pattern to use for replace operations,
12: /// based on the supplied pattern that uses this provider.
13: /// </summary>
14: /// <param name="pattern">The pattern to convert using this provider.</param>
15: /// <returns>The regular expression match pattern to use for
16: /// replace operations.</returns>
17: string GetReplacePattern(string pattern);
The core search code uses our built-in regular expression engine to perform searching. Therefore search patterns to our search code must be provided in regular expression syntax.
So what ISearchPatternProvider’s two methods do is provide a conversion from your custom pattern format to a regular expression equivalent. Regular expression substitutions are fully supported too if you wish.
An example
Say that you make a custom pattern format where the find text is normal text except that the _ character has been changed to mean any digit character.
To accomplish this, you’d make a custom ISearchPatternProvider that implements a GetFindPattern method that regular expression escapes all the normal text, except converts the _ character instances to [0-9], which means any digit.
Therefore once implemented, if the end user chooses your custom pattern provider and they use this find pattern:
$_.__
The result of your GetFindPattern conversion to regular expression format would be:
\$[0-9]\.[0-9][0-9]
This would match any $ character followed by a single digit, then a period, then two more digits.
Of course that is a simple sample, but you could easily create your own robust format. This sort of extensibility functionality is what you’ll find throughout the SyntaxEditor for WPF product.