12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- 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(`^(\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) }
|