Add support for headline CUSTOM_ID property & linking

this introduces the PropertyDrawer node to make it easier to access the
properties associated to a headline - normal drawers don't parse their content
into kv pairs
This commit is contained in:
Niklas Fasching 2018-12-19 13:25:12 +01:00
parent ec895cbe83
commit aa42998dbc
8 changed files with 79 additions and 14 deletions

View file

@ -10,8 +10,13 @@ type Drawer struct {
Children []Node
}
type PropertyDrawer struct {
Properties [][]string
}
var beginDrawerRegexp = regexp.MustCompile(`^(\s*):(\S+):\s*$`)
var endDrawerRegexp = regexp.MustCompile(`^(\s*):END:\s*$`)
var propertyRegexp = regexp.MustCompile(`^(\s*):(\S+):(\s+(.*)$|\s*$)`)
func lexDrawer(line string) (token, bool) {
if m := endDrawerRegexp.FindStringSubmatch(line); m != nil {
@ -23,7 +28,11 @@ func lexDrawer(line string) (token, bool) {
}
func (d *Document) parseDrawer(i int, parentStop stopFn) (int, Node) {
drawer, start := Drawer{Name: strings.ToUpper(d.tokens[i].content)}, i
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) {
@ -49,3 +58,34 @@ func (d *Document) parseDrawer(i int, parentStop stopFn) (int, Node) {
}
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])
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
}