Skip to content

Commit

Permalink
fix: new NS-free regex pattern-finding implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
photovirus committed Dec 9, 2022
1 parent c6f6a80 commit cfe5504
Showing 1 changed file with 21 additions and 11 deletions.
32 changes: 21 additions & 11 deletions Sources/Lingo/StringInterpolator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@ import Foundation

final class StringInterpolator {

private static let regularExpression = try! NSRegularExpression(pattern: "\\%\\{[^\\}]*\\}", options: []) // swiftlint:disable:this force_try
private static let regexPattern = "\\%\\{[^\\}]*\\}"

/// Input string is in format: "You have %{count} unread messages".
/// The function finds all placeholders and replaces them with a value specified in interpolations dictionary
func interpolate(_ rawString: String, with interpolations: [String: Any]) -> String {
var result = rawString
let matches = StringInterpolator.regularExpression.matches(in: rawString, options: [], range: NSRange.init(location: 0, length: rawString.count))

for match in matches {
let range: NSRange = match.range
let ranges: [Range<String.Index>] = findRanges(in: rawString, startingFrom: rawString.startIndex)

return ranges.reduce(into: rawString) { result, range in

// Extract whole capture group string. Will contain string like: "%{count}"
let startIndex = rawString.index(rawString.startIndex, offsetBy: range.location)
let endIndex = rawString.index(startIndex, offsetBy: range.length)
let matchedString = String(rawString[startIndex..<endIndex])
let matchedString = String(rawString[range.lowerBound..<range.upperBound])

// Extract the key from `matchedString`. Will contain string like: "count"
let keyStartIndex = matchedString.index(matchedString.startIndex, offsetBy: 2)
Expand All @@ -26,9 +23,22 @@ final class StringInterpolator {
if let interpolation = interpolations[key] {
result = result.replacingOccurrences(of: matchedString, with: "\(interpolation)")
}

}
}

func findRanges(in text: String, startingFrom start: String.Index) -> [Range<String.Index>] {
let end = text.endIndex
guard let range = text.range(of: Self.regexPattern, options: .regularExpression,
range: start..<end) else {
return ([])
}

return result
let cursor = range.upperBound

let recursiveResult = self.findRanges(in: text, startingFrom: cursor)

return ([range] + recursiveResult)

}

}

0 comments on commit cfe5504

Please sign in to comment.