Skip to content

Instantly share code, notes, and snippets.

@seoh
Created September 23, 2014 17:20
Show Gist options
  • Save seoh/7673fbcd19ab792f02b5 to your computer and use it in GitHub Desktop.
Save seoh/7673fbcd19ab792f02b5 to your computer and use it in GitHub Desktop.
Swift Comparison and String Literal
// http://nshipster.com/swift-comparison-protocols/
import Foundation
struct CSSSelector {
let selector: String
struct Specificity {
let id: Int
let `class`: Int
let element: Int
init(_ components: [String]) {
var (id, `class`, element) = (0, 0, 0)
for token in components {
if token.hasPrefix("#") {
id++
} else if token.hasPrefix(".") {
`class`++
} else {
element++
}
}
self.id = id
self.`class` = `class`
self.element = element
}
}
let specificity: Specificity
init(_ string: String) {
self.selector = string
// Naïve tokenization, ignoring operators, pseudo-selectors, and `style=`.
let components: [String] = self.selector.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
self.specificity = Specificity(components)
}
}
extension CSSSelector: StringLiteralConvertible {
typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
typealias UnicodeScalarLiteralType = StringLiteralType
static func convertFromStringLiteral(value: StringLiteralType) -> CSSSelector {
return self(value)
}
static func convertFromExtendedGraphemeClusterLiteral(value: ExtendedGraphemeClusterLiteralType) -> CSSSelector {
return self(value)
}
static func convertFromUnicodeScalarLiteral(value: UnicodeScalarLiteralType) -> CSSSelector {
return self(value)
}
}
extension CSSSelector: Equatable {}
// MARK: Equatable
func ==(lhs: CSSSelector, rhs: CSSSelector) -> Bool {
// Naïve equality that uses string comparison rather than resolving equivalent selectors
return lhs.selector == rhs.selector
}
extension CSSSelector.Specificity: Comparable {}
// MARK: Comparable
func <(lhs: CSSSelector.Specificity, rhs: CSSSelector.Specificity) -> Bool {
return lhs.id < rhs.id ||
lhs.`class` < rhs.`class` ||
lhs.element < rhs.element
}
// MARK: Equatable
func ==(lhs: CSSSelector.Specificity, rhs: CSSSelector.Specificity) -> Bool {
return lhs.id == rhs.id &&
lhs.`class` == rhs.`class` &&
lhs.element == rhs.element
}
let a: CSSSelector = "#logo"
let b: CSSSelector = "html body #logo"
let c: CSSSelector = "body div #logo"
let d: CSSSelector = ".container #logo"
println(b == c) // false
println(b.specificity == c.specificity) // true
println(c.specificity < a.specificity) // false
println(d.specificity > c.specificity) // true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment