Add workaround for \v regex metacharacter (fix #713)

This commit is contained in:
1024jp 2017-07-30 21:14:58 +09:00
parent 875405adb3
commit 4e6eaa26c7
3 changed files with 33 additions and 1 deletions

View File

@ -13,6 +13,7 @@ develop
### Fixes
- Fix an issue where the regular expression didn't handle `\v` metacharacter correctly.
- Fix an issue where the selection of encoding menu in toolbar didn't restore to the previous one when encoding reinterpretation was failed.
- [AppStore ver.] Fix an issue where acknowledgement window was empty.

View File

@ -85,8 +85,18 @@ final class TextFind {
}
if settings.usesRegularExpression {
let sanitizedFindString: String = {
// replace `\v` with `\u000b`
// -> Because NSRegularExpression cannot handle `\v` correctly. (2017-07 on macOS 10.12)
// cf. https://github.com/coteditor/CotEditor/issues/713
if findString.contains("\\v") {
return findString.replacingOccurrences(of: "(?<!\\\\)\\\\v", with: "\\\\u000b", options: .regularExpression)
}
return findString
}()
do {
self.regex = try NSRegularExpression(pattern: findString, options: settings.regexOptions)
self.regex = try NSRegularExpression(pattern: sanitizedFindString, options: settings.regexOptions)
} catch {
let failureReason: String? = (error as? LocalizedError)?.failureReason
throw TextFindError.regularExpression(reason: failureReason)

View File

@ -98,6 +98,27 @@ class TextFindTests: XCTestCase {
}
func testVerticalTabFind() {
let text = "\u{b}000\\v000\n"
let findString = "\\v"
let settings = TextFind.Settings(usesRegularExpression: true,
isWrap: true,
regexOptions: [.caseInsensitive],
unescapesReplacementString: true)
let textFind = try! TextFind(for: text, findString: findString, settings: settings)
let result = textFind.find(forward: false)
XCTAssertEqual(result.count, 1)
// wrong pattern with raw NSRegularExpression
let regex = try! NSRegularExpression(pattern: findString)
let numberOfMatches = regex.numberOfMatches(in: text, range: NSRange(location: 0, length: text.utf16.count))
XCTAssertEqual(numberOfMatches, 2)
}
func testSingleRegexFindAndReplacement() {
let findString = "(?!=a)b(c)(?=d)"