Skip to content

Instantly share code, notes, and snippets.

@ollieatkinson
Last active September 15, 2020 14:41
Show Gist options
  • Save ollieatkinson/50b1259a2e4d84b6f3ba3181394fae03 to your computer and use it in GitHub Desktop.
Save ollieatkinson/50b1259a2e4d84b6f3ba3181394fae03 to your computer and use it in GitHub Desktop.
Candy for NSRegularExpression matching. Match allows for indexed and named capture groups
import Foundation
extension NSRegularExpression {
@dynamicMemberLookup
public struct Match {
let string: String
let result: [NSTextCheckingResult]
private lazy var iterator = result.makeIterator()
public init(_ string: String, _ result: [NSTextCheckingResult]) {
self.string = string
self.result = result
}
}
public func matches(in string: String, options: MatchingOptions = []) -> Match {
.init(string, matches(in: string, options: options, range: string.nsRange))
}
public func first(in string: String) -> Match? {
firstMatch(in: string, range: string.nsRange).map { .init(string, [$0]) }
}
public static func ~= (regex: NSRegularExpression, string: String) -> Bool {
regex.first(in: string) != nil
}
}
extension NSRegularExpression.Match {
public subscript<T>(dynamicMember keyPath: KeyPath<[NSTextCheckingResult], T>) -> T {
result[keyPath: keyPath]
}
}
extension NSRegularExpression.Match: Sequence, IteratorProtocol {
public mutating func next() -> NSTextCheckingResult? {
iterator.next()
}
}
extension NSRegularExpression.Match {
public subscript(name: String) -> String? {
result.lazy.map{ $0.range(withName: name) }.compactMap(string(at:)).first
}
public subscript(idx: Int) -> String? {
result.lazy.map{ $0.range(at: idx) }.compactMap(string(at:)).first
}
private func string(at ns: NSRange) -> String? {
guard ns.location != NSNotFound else { return nil }
guard let range = Range<String.Index>(ns, in: string) else { return nil }
return String(string[range])
}
}
extension String {
public var regex: NSRegularExpression? { try? regex() }
public func regex(_ options: NSRegularExpression.Options = []) throws -> NSRegularExpression {
try NSRegularExpression(pattern: self, options: options)
}
}
extension String {
var nsRange: NSRange {
.init(location: 0, length: count)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment