krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Sources/OrgDocument/Buffer.swift

ab6ccec56eca03d0dadf2c9332aab10c4490eb62
orgstar/Sources/OrgDocument/Buffer.swift history · blame · raw

41 lines · 1545 bytes

 1import Foundation
 2import OrgCore
 3
 4/// Where an open document's live state is kept: the editor while one shows it, a
 5/// `StateBuffer` before that.
 6@MainActor
 7public protocol DocumentBuffer: AnyObject {
 8    var document: DocumentState { get }
 9    /// Selected ranges; the first holds the caret.
10    var selection: [Range<Int>] { get }
11    /// Runs a command at the selection as one undoable change.
12    func perform(_ command: any OrgCommand, now: Date, answers: [String: String]) -> CommandStep
13    /// Applies a change made outside typing (save, disk change, revert) and updates whatever
14    /// shows the document.
15    func update<T>(_ change: (inout DocumentState) throws -> T) rethrows -> T
16}
17
18@MainActor
19public final class StateBuffer: DocumentBuffer {
20    public private(set) var document: DocumentState
21    public var selection: [Range<Int>] = [0..<0]
22    public var options: EditingOptions = .org
23
24    public init(_ document: DocumentState) {
25        self.document = document
26    }
27
28    public func perform(_ command: any OrgCommand, now: Date, answers: [String: String]) -> CommandStep {
29        do {
30            let step = try document.run(command, selection: selection, now: now, answers: answers, options: options)
31            if case .commit(let result) = step, let new = result.selection { selection = new }
32            return step
33        } catch {
34            return .failed("\(error)")
35        }
36    }
37
38    public func update<T>(_ change: (inout DocumentState) throws -> T) rethrows -> T {
39        try change(&document)
40    }
41}