go-org-orgwiki/org/keyword.go

85 lines
2 KiB
Go

package org
import (
"regexp"
"strings"
)
type Keyword struct {
Key string
Value string
}
type NodeWithMeta struct {
Node Node
Meta map[string]string
}
type Comment struct{ Content string }
var keywordRegexp = regexp.MustCompile(`^(\s*)#\+([^:]+):\s(.*)`)
var commentRegexp = regexp.MustCompile(`^(\s*)#(.*)`)
var affiliatedKeywordRegexp = regexp.MustCompile(`^(CAPTION)$`)
func lexKeywordOrComment(line string) (token, bool) {
if m := keywordRegexp.FindStringSubmatch(line); m != nil {
return token{"keyword", len(m[1]), m[2], m}, true
} else if m := commentRegexp.FindStringSubmatch(line); m != nil {
return token{"comment", len(m[1]), m[2], m}, true
}
return nilToken, false
}
func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) {
k := parseKeyword(d.tokens[i])
if affiliatedKeywordRegexp.MatchString(k.Key) {
consumed, node := d.parseAffiliated(i, stop)
if consumed != 0 {
return consumed, node
}
} else {
d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n")
}
return 1, k
}
func (d *Document) parseComment(i int, stop stopFn) (int, Node) {
return 1, Comment{d.tokens[i].content}
}
func (d *Document) parseAffiliated(i int, stop stopFn) (int, Node) {
start, meta := i, map[string]string{}
for ; !stop(d, i) && d.tokens[i].kind == "keyword"; i++ {
k := parseKeyword(d.tokens[i])
if !affiliatedKeywordRegexp.MatchString(k.Key) {
return 0, nil
}
if value, ok := meta[k.Key]; ok {
meta[k.Key] = value + " " + k.Value
} else {
meta[k.Key] = k.Value
}
}
if stop(d, i) {
return 0, nil
}
consumed, node := 0, (Node)(nil)
if t := d.tokens[i]; t.kind == "text" {
if nodes := d.parseInline(t.content); len(nodes) == 1 && isImageOrVideoLink(nodes[0]) {
consumed, node = 1, Line{nodes[:1]}
}
} else {
consumed, node = d.parseOne(i, stop)
}
if consumed == 0 || node == nil {
return 0, nil
}
i += consumed
return i - start, NodeWithMeta{node, meta}
}
func parseKeyword(t token) Keyword {
k, v := t.matches[2], t.matches[3]
k = strings.ToUpper(k)
return Keyword{k, v}
}