Something went wrong. Try again.
A mirror to work around a broken repository.
Something went wrong. Try again.
2.8 kB · 81 lines
Swift
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182import AppKit
extension NSAttributedString.Key { static let dividerBlockID: NSAttributedString.Key = NSAttributedString.Key("dividerBlockID") static let newlineBeforeDivider: NSAttributedString.Key = NSAttributedString.Key("newlineBeforeDivider") static let newlineAfterDivider: NSAttributedString.Key = NSAttributedString.Key("newlineBeforeDivider")}
extension NSAttributedString { func enumerateBlockRanges(in fullRange: NSRange, _ body: (UUID?, NSRange, inout Bool) -> Void) { do { var currentBlockID: UUID? = nil var currentLocation = 0 var shouldStop = false
enumerateAttribute(.dividerBlockID, in: fullRange) { value, range, shouldStopPtr in if let value { let previousRange = NSRange(location: currentLocation, length: range.location - currentLocation) body(currentBlockID, previousRange, &shouldStop)
let blockID = value as! UUID currentLocation = range.upperBound currentBlockID = blockID }
shouldStopPtr.pointee = ObjCBool(shouldStop) }
body(currentBlockID, NSRange(location: currentLocation, length: currentLocation.distance(to: length)), &shouldStop) } }
func blockRanges(firstBlockID: UUID) -> [UUID: NSRange] { var ranges: [UUID: NSRange] = [:]
enumerateBlockRanges(in: NSRange(location: 0, length: length)) { uuid, range, shouldStop in ranges[uuid ?? firstBlockID] = range }
return ranges }
func rangeIntersectsReadonlySpan(_ range: NSRange) -> Bool { if range.length == 0 { var effectiveRange = NSRange() let fullRange = NSRange(location: 0, length: length) if safeAttribute(.dividerBlockID, at: range.location, longestEffectiveRange: &effectiveRange, in: fullRange) != nil { return range.location != effectiveRange.upperBound && range.location != effectiveRange.lowerBound } return false }
var intersects = false enumerateAttribute(.dividerBlockID, in: range) { value, _, shouldStop in if value != nil { intersects = true shouldStop.pointee = ObjCBool(true) } }
return intersects }}
extension NSAttributedString { func safeAttribute(_ attrName: NSAttributedString.Key, at location: Int, effectiveRange range: NSRangePointer?) -> Any? { let fullRange = NSRange(location: 0, length: length) guard fullRange.contains(location) else { return nil } return attribute(attrName, at: location, effectiveRange: range) }
func safeAttribute(_ attrName: NSAttributedString.Key, at location: Int, longestEffectiveRange range: NSRangePointer?, in rangeLimit: NSRange) -> Any? { let fullRange = NSRange(location: 0, length: length) guard fullRange.contains(location) else { return nil } guard fullRange.intersection(rangeLimit) != nil else { return nil } return attribute(attrName, at: location, longestEffectiveRange: range, in: rangeLimit) }
}