diff --git a/CodeEdit/Features/Documents/WorkspaceDocument+Find.swift b/CodeEdit/Features/Documents/WorkspaceDocument+Find.swift index 4f474020c7..1a426cfd9f 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument+Find.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument+Find.swift @@ -14,10 +14,11 @@ extension WorkspaceDocument.SearchState { /// /// - Returns: A modified search term according to the specified search mode. func getSearchTerm(_ query: String) -> String { - let newQuery = caseSensitive ? query : query.lowercased() + let newQuery = stripSpecialCharacters(from: (caseSensitive ? query : query.lowercased())) guard let mode = selectedMode.third else { return newQuery } + switch mode { case .Containing: return "*\(newQuery)*" @@ -30,6 +31,16 @@ extension WorkspaceDocument.SearchState { } } + func stripSpecialCharacters(from string: String) -> String { + let regex = try? NSRegularExpression(pattern: "[^a-zA-Z0-9]+", options: .caseInsensitive) + return regex!.stringByReplacingMatches( + in: string, + options: [], + range: NSRange(location: 0, length: string.utf16.count), + withTemplate: "*" + ) + } + /// Generates a regular expression pattern based on the specified query and search mode. /// /// - Parameter query: The original user query string. @@ -41,21 +52,23 @@ extension WorkspaceDocument.SearchState { /// Except its using the word boundary anchor(\b) instead of the asterisk(\*). /// This is needed to highlight the search results correctly. func getRegexPattern(_ query: String) -> String { + let newQuery = NSRegularExpression.escapedPattern(for: query.trimmingCharacters(in: .whitespacesAndNewlines)) + guard let mode = selectedMode.third else { - return query + return newQuery } switch mode { case .Containing: - return "\(query)" + return "\(newQuery)" case .StartingWith: - return "\\b\(query)" + return "\\b\(newQuery)" case .EndingWith: - return "\(query)\\b" + return "\(newQuery)\\b" case .MatchingWord: - return "\\b\(query)\\b" + return "\\b\(newQuery)\\b" default: - return query + return newQuery } } @@ -175,7 +188,7 @@ extension WorkspaceDocument.SearchState { // Attempt to create a regular expression from the provided query guard let regex = try? NSRegularExpression( pattern: query, - options: caseSensitive ? [] : [.caseInsensitive] + options: caseSensitive ? [] : .caseInsensitive ) else { await setStatus(.failed(errorMessage: "Invalid regular expression.")) return diff --git a/CodeEditTests/Features/Documents/WorkspaceDocument+SearchState+FindTests.swift b/CodeEditTests/Features/Documents/WorkspaceDocument+SearchState+FindTests.swift index ca3457ec57..b002063905 100644 --- a/CodeEditTests/Features/Documents/WorkspaceDocument+SearchState+FindTests.swift +++ b/CodeEditTests/Features/Documents/WorkspaceDocument+SearchState+FindTests.swift @@ -47,9 +47,9 @@ final class FindTests: XCTestCase { for index in 0..