123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- package org
-
- import (
- "fmt"
- "regexp"
- "strings"
- "unicode"
- )
-
- type Outline struct {
- *Section
- last *Section
- count int
- }
-
- type Section struct {
- Headline *Headline
- Parent *Section
- Children []*Section
- }
-
- type Headline struct {
- Index int
- Lvl int
- Status string
- Priority string
- Properties *PropertyDrawer
- Title []Node
- Tags []string
- Children []Node
- }
-
- var headlineRegexp = regexp.MustCompile(`^([*]+)\s+(.*)`)
- var tagRegexp = regexp.MustCompile(`(.*?)\s+(:[A-Za-z0-9_@#%:]+:\s*$)`)
-
- func lexHeadline(line string) (token, bool) {
- if m := headlineRegexp.FindStringSubmatch(line); m != nil {
- return token{"headline", len(m[1]), m[2], m}, true
- }
- return nilToken, false
- }
-
- func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) {
- t, headline := d.tokens[i], Headline{}
- headline.Lvl = t.lvl
-
- headline.Index = d.addHeadline(&headline)
-
- text := t.content
- todoKeywords := strings.FieldsFunc(d.Get("TODO"), func(r rune) bool { return unicode.IsSpace(r) || r == '|' })
- for _, k := range todoKeywords {
- if strings.HasPrefix(text, k) && len(text) > len(k) && unicode.IsSpace(rune(text[len(k)])) {
- headline.Status = k
- text = text[len(k)+1:]
- break
- }
- }
-
- if len(text) >= 4 && text[0:2] == "[#" && strings.Contains("ABC", text[2:3]) && text[3] == ']' {
- headline.Priority = text[2:3]
- text = strings.TrimSpace(text[4:])
- }
-
- if m := tagRegexp.FindStringSubmatch(text); m != nil {
- text = m[1]
- headline.Tags = strings.FieldsFunc(m[2], func(r rune) bool { return r == ':' })
- }
-
- headline.Title = d.parseInline(text)
-
- stop := func(d *Document, i int) bool {
- return parentStop(d, i) || d.tokens[i].kind == "headline" && d.tokens[i].lvl <= headline.Lvl
- }
- consumed, nodes := d.parseMany(i+1, stop)
- if len(nodes) > 0 {
- if d, ok := nodes[0].(PropertyDrawer); ok {
- headline.Properties = &d
- nodes = nodes[1:]
- }
- }
- headline.Children = nodes
- return consumed + 1, headline
- }
-
- func (h Headline) ID() string {
- if customID, ok := h.Properties.Get("CUSTOM_ID"); ok {
- return customID
- }
- return fmt.Sprintf("headline-%d", h.Index)
- }
-
- func (parent *Section) add(current *Section) {
- if parent.Headline == nil || parent.Headline.Lvl < current.Headline.Lvl {
- parent.Children = append(parent.Children, current)
- current.Parent = parent
- } else {
- parent.Parent.add(current)
- }
- }
-
- func (n Headline) String() string { return orgWriter.WriteNodesAsString(n) }
|