import Foundation import OrgCore /// A range of a file to read rather than edit: its style runs as segments, with the brackets /// and targets of described links hidden (`org-link-descriptive`) and folded drawers shown as /// their first line and `…`, as the editor shows them. public enum ReadingText { public struct Segment: Sendable, Equatable { public var text: String public var roles: Set /// The link this text belongs to. public var link: OrgLink? /// Where the text starts in the file. public var offset: Int /// A pretty sub/superscript's body: true raised, false lowered. public var superscript: Bool? } /// How the text shows, as the editor's display settings make it. public struct Display: Sendable { /// Link brackets and targets, and emphasis markers, shown; no pretty entities. public var showMarkup = false /// `org-hide-emphasis-markers`, `org-pretty-entities` and its braces. public var options = EditingOptions.org /// Colors code in src blocks. public var highlighter: (any CodeHighlighter)? public init(showMarkup: Bool = false, options: EditingOptions = .org, highlighter: (any CodeHighlighter)? = nil) { self.showMarkup = showMarkup self.options = options self.highlighter = highlighter } } /// `folded` are drawers' and blocks' hidden ranges (`Wrapper.hidden`). public static func segments(_ tree: OrgTree, in range: Range, folded: [Range] = [], display: Display = Display()) -> [Segment] { let text = tree.text as NSString let runs = Presentation.styles(tree, in: range, highlighter: display.highlighter) // A fold hides from the end of the opening line through the closing line, so the // marker sits on the opening line. let folds = folded.compactMap { r -> Range? in guard r.lowerBound > range.lowerBound, r.lowerBound <= range.upperBound else { return nil } let end = r.upperBound > r.lowerBound && r.upperBound <= text.length && text.character(at: r.upperBound - 1) == 10 ? r.upperBound - 1 : r.upperBound return (r.lowerBound - 1)..