/// A detached modifier with its marker, nestling level, task status (if set), /// and content. struct DetachedModifier { let marker: Character let level: Int let status: TaskStatus? let statusIndex: String.Index? let content: Substring /// Finds and parses a detached modifier if present. The accepting markers /// is used to reduce the markers being parsed. static func parse(_ line: Substring, accepting markers: ASCIIByteSet) -> DetachedModifier? { let utf8 = line.utf8 let end = utf8.endIndex var i = utf8.startIndex while i < end, ASCIIHelper.isWhitespace(utf8[i]) { i = utf8.index(after: i) } guard i < end else { return nil } let markerByte = utf8[i] guard markers.contains(markerByte) else { return nil } var level = 0 var run = i while run < end, utf8[run] == markerByte { level += 1 run = utf8.index(after: run) } guard run < end, ASCIIHelper.isWhitespace(utf8[run]) else { return nil } var rest = run while rest < end, ASCIIHelper.isWhitespace(utf8[rest]) { rest = utf8.index(after: rest) } var status: TaskStatus? var statusIndex: String.Index? var contentStart = rest if rest < end, utf8[rest] == UInt8(ascii: "(") { let markerPosition = utf8.index(after: rest) if markerPosition < end { let closePosition = utf8.index(after: markerPosition) let statusByte = utf8[markerPosition] if closePosition < end, utf8[closePosition] == UInt8(ascii: ")"), let parsed = TaskStatus(markerByte: statusByte) { status = parsed statusIndex = markerPosition contentStart = utf8.index(after: closePosition) } } } return DetachedModifier( marker: Character(Unicode.Scalar(markerByte)), level: level, status: status, statusIndex: statusIndex, content: TextHelper.whitespaceTrimmed(line[contentStart...]) ) } }