-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
package org
import (
"regexp"
"strings"
)
type Drawer struct {
Name string
Children []Node
}
type PropertyDrawer struct {
Properties [][]string
}
var beginDrawerRegexp = regexp.MustCompile(`^(\s*):(\S+):\s*$`)
var endDrawerRegexp = regexp.MustCompile(`(?i)^(\s*):END:\s*$`)
var propertyRegexp = regexp.MustCompile(`^(\s*):(\S+):(\s+(.*)$|$)`)
func lexDrawer(line string) (token, bool) {
if m := endDrawerRegexp.FindStringSubmatch(line); m != nil {
return token{"endDrawer", len(m[1]), "", m}, true
} else if m := beginDrawerRegexp.FindStringSubmatch(line); m != nil {
return token{"beginDrawer", len(m[1]), strings.ToUpper(m[2]), m}, true
}
return nilToken, false
}
func (d *Document) parseDrawer(i int, parentStop stopFn) (int, Node) {
name := strings.ToUpper(d.tokens[i].content)
if name == "PROPERTIES" {
return d.parsePropertyDrawer(i, parentStop)
}
drawer, start := Drawer{Name: name}, i
i++
stop := func(d *Document, i int) bool {
if parentStop(d, i) {
return true
}
kind := d.tokens[i].kind
return kind == "beginDrawer" || kind == "endDrawer" || kind == "headline"
}
for {
consumed, nodes := d.parseMany(i, stop)
i += consumed
drawer.Children = append(drawer.Children, nodes...)
if i < len(d.tokens) && d.tokens[i].kind == "beginDrawer" {
p := Paragraph{[]Node{Text{":" + d.tokens[i].content + ":", false}}}
drawer.Children = append(drawer.Children, p)
i++
} else {
break
}
}
if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" {
i++
}
return i - start, drawer
}
func (d *Document) parsePropertyDrawer(i int, parentStop stopFn) (int, Node) {
drawer, start := PropertyDrawer{}, i
i++
stop := func(d *Document, i int) bool {
return parentStop(d, i) || (d.tokens[i].kind != "text" && d.tokens[i].kind != "beginDrawer")
}
for ; !stop(d, i); i++ {
m := propertyRegexp.FindStringSubmatch(d.tokens[i].matches[0])
if m == nil {
return 0, nil
}
k, v := strings.ToUpper(m[2]), strings.TrimSpace(m[4])
drawer.Properties = append(drawer.Properties, []string{k, v})
}
if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" {
i++
} else {
return 0, nil
}
return i - start, drawer
}
func (d *PropertyDrawer) Get(key string) (string, bool) {
if d == nil {
return "", false
}
for _, kvPair := range d.Properties {
if kvPair[0] == key {
return kvPair[1], true
}
}
return "", false
}
func (n Drawer) String() string { return orgWriter.WriteNodesAsString(n) }
func (n PropertyDrawer) String() string { return orgWriter.WriteNodesAsString(n) }