 ///     - the paths can be normalized to equal Paths.
 ///
 public func ~=(lhs: Path, rhs: Path) -> Bool {
-  return lhs == rhs
-    || lhs.normalize() == rhs.normalize()
+    return lhs == rhs
+        || lhs.normalize() == rhs.normalize()
 }
 
 


/// Defines a strict total order over Paths based on their underlying string representation.
public func <(lhs: Path, rhs: Path) -> Bool {
  return lhs.path < rhs.path
}




/// Appends a Path fragment to another Path to produce a new Path
public func +(lhs: Path, rhs: Path) -> Path {
    return lhs.path + rhs.path
}

/// Appends a String fragment to another Path to produce a new Path
public func +(lhs: Path, rhs: String) -> Path {
    return lhs.path + rhs
}

/// Appends a String fragment to another String to produce a new Path
internal func +(lhs: String, rhs: String) -> Path {
    if rhs.hasPrefix(Path.separator) {
        // Absolute paths replace relative paths
        return Path(rhs)
    } else {
        var lSlice = NSString(string: lhs).pathComponents.fullSlice
        var rSlice = NSString(string: rhs).pathComponents.fullSlice
        
        // Get rid of trailing "/" at the left side
        if lSlice.count > 1 && lSlice.last == Path.separator {
            lSlice.removeLast()
        }
        
        // Advance after the first relevant "."
        lSlice = lSlice.filter { $0 != "." }.fullSlice
        rSlice = rSlice.filter { $0 != "." }.fullSlice
        
        // Eats up trailing components of the left and leading ".." of the right side
        while lSlice.last != ".." && rSlice.first == ".." {
            if (lSlice.count > 1 || lSlice.first != Path.separator) && !lSlice.isEmpty {
                // A leading "/" is never popped
                lSlice.removeLast()
            }
            if !rSlice.isEmpty {
                rSlice.removeFirst()
            }
            
            switch (lSlice.isEmpty, rSlice.isEmpty) {
            case (true, _):
                break
            case (_, true):
                break
            default:
                continue
            }
        }
        
        return Path(components: lSlice + rSlice)
    }
}

extension Array {
    var fullSlice: ArraySlice<Element> {
        return self[0..<self.endIndex]
    }
}
