krz/orgstar

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

Tests/OrgCoreTests/ObjectParseTests.swift

main
orgstar/Tests/OrgCoreTests/ObjectParseTests.swift history · blame · raw

58 lines · 3148 bytes

3 symbols in this file
 1import Foundation
 2import Testing
 3@testable import OrgCore
 4
 5/// Where org-element finds objects of each kind, against our tree.
 6struct ObjectParseTests {
 7    static let oracle = ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil
 8
 9    static let text = """
10        * Objects
11        Entities \\alpha, \\alpha{}beta, \\nbsp and \\notanentity.
12        Scripts x_1 y^2 a_{b c} d^{e} f_(g) h^* snake_case_name n^-1 e_{x_{y}} 2_1.5a.
13        Not after space _x ^y.
14        Math $x$ and $x+y$, $$e=mc^2$$ and \\(a^2\\) and \\[b\\] and \\frac{1}{2} and \\textbf[opt]{bold}.
15        Money $5 and $10, not math $ x$ nor $x $.
16        A radio <<<Target Word>>> here; the target word links, Target Words don't.
17        In *bold \\beta x_2* and [[link][\\gamma]].
18        \\begin{equation}
19        x = y^2
20        \\end{equation}
21          \\begin{align*} a \\end{align*}
22        \\begin{x}
23        never closed
24        """ + "\n"
25
26    static let kinds: [(lisp: String, ours: [SyntaxKind])] = [
27        ("entity", [.entity]), ("subscript", [.subscript]), ("superscript", [.superscript]),
28        ("latex-fragment", [.latexFragment]), ("radio-target", [.radioTarget]), ("latex-environment", [.latexEnvironment]),
29    ]
30
31    func ours(_ kinds: [SyntaxKind]) -> [String] {
32        OrgParser.parse(Self.text).root.descendants().filter { kinds.contains($0.kind) }.map { "\($0.range.lowerBound) \($0.range.upperBound)" }
33    }
34
35    @Test(.enabled(if: oracle))
36    func objectsMatchOrgElement() throws {
37        let forms = Self.kinds.map { kind in
38            """
39            (mapconcat (lambda (o) (format "%d %d" (1- (org-element-begin o))
40                                    (1- (save-excursion (goto-char (org-element-end o)) (skip-chars-backward " \\t") (point)))))
41                       (org-element-map (org-element-parse-buffer) '\(kind.lisp) #'identity) ",")
42            """
43        }
44        let emacs = try EmacsOracle.evaluate(Self.text, "(with-current-buffer (find-file-noselect \"oracle.org\") (list \(forms.joined(separator: " "))))")
45        for (i, kind) in Self.kinds.enumerated() {
46            let theirs = emacs[i].split(separator: ",").map(String.init)
47            #expect(ours(kind.ours) == theirs, "\(kind.lisp)")
48        }
49        // Radio links: links whose text is a radio target's.
50        let links = try EmacsOracle.evaluate(Self.text, """
51            (with-current-buffer (find-file-noselect "oracle.org")
52              (list (mapconcat (lambda (o) (format "%d %d" (1- (org-element-begin o)) (1- (save-excursion (goto-char (org-element-end o)) (skip-chars-backward " \\t") (point)))))
53                               (org-element-map (org-element-parse-buffer) 'link (lambda (l) (and (equal (org-element-property :type l) "radio") l))) ",")))
54            """)
55        let radio = OrgParser.parse(Self.text).root.descendants().filter { $0.kind == .link && $0.tokens.first { $0.kind == .linkPath } == nil && !$0.text.hasPrefix("[") && !$0.text.hasPrefix("<") && !$0.text.contains(":") }
56        #expect(radio.map { "\($0.range.lowerBound) \($0.range.upperBound)" } == links[0].split(separator: ",").map(String.init))
57    }
58}