Support basic #+INCLUDE (src/example/export block only)
including org files is more complex - e.g. footnotes need to be namespaced to their source file. org does this by prefixing each included files footnotes with a number - but even that is not enough as it doesn't guarantee uniqueness. As I don't have a usecase for it, I'll avoid the additional complexity for now.
This commit is contained in:
parent
04df30a7b5
commit
2947d7632d
13 changed files with 150 additions and 26 deletions
|
@ -2,10 +2,15 @@ package org
|
|||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Comment struct{ Content string }
|
||||
|
||||
type Keyword struct {
|
||||
Key string
|
||||
Value string
|
||||
|
@ -21,11 +26,16 @@ type Metadata struct {
|
|||
HTMLAttributes [][]string
|
||||
}
|
||||
|
||||
type Comment struct{ Content string }
|
||||
type Include struct {
|
||||
Keyword
|
||||
Resolve func() Node
|
||||
}
|
||||
|
||||
var keywordRegexp = regexp.MustCompile(`^(\s*)#\+([^:]+):(\s+(.*)|(\s*)$)`)
|
||||
var commentRegexp = regexp.MustCompile(`^(\s*)#(.*)`)
|
||||
|
||||
var includeFileRegexp = regexp.MustCompile(`(?i)^"([^"]+)" (src|example|export) (\w+)$`)
|
||||
|
||||
func lexKeywordOrComment(line string) (token, bool) {
|
||||
if m := keywordRegexp.FindStringSubmatch(line); m != nil {
|
||||
return token{"keyword", len(m[1]), m[2], m}, true
|
||||
|
@ -41,18 +51,23 @@ func (d *Document) parseComment(i int, stop stopFn) (int, Node) {
|
|||
|
||||
func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) {
|
||||
k := parseKeyword(d.tokens[i])
|
||||
if k.Key == "CAPTION" || k.Key == "ATTR_HTML" {
|
||||
switch k.Key {
|
||||
case "INCLUDE":
|
||||
return d.newInclude(k)
|
||||
case "CAPTION", "ATTR_HTML":
|
||||
consumed, node := d.parseAffiliated(i, stop)
|
||||
if consumed != 0 {
|
||||
return consumed, node
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
if _, ok := d.BufferSettings[k.Key]; ok {
|
||||
d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n")
|
||||
} else {
|
||||
d.BufferSettings[k.Key] = k.Value
|
||||
}
|
||||
return 1, k
|
||||
}
|
||||
if _, ok := d.BufferSettings[k.Key]; ok {
|
||||
d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n")
|
||||
} else {
|
||||
d.BufferSettings[k.Key] = k.Value
|
||||
}
|
||||
return 1, k
|
||||
}
|
||||
|
||||
func (d *Document) parseAffiliated(i int, stop stopFn) (int, Node) {
|
||||
|
@ -89,3 +104,21 @@ func parseKeyword(t token) Keyword {
|
|||
k = strings.ToUpper(k)
|
||||
return Keyword{k, v}
|
||||
}
|
||||
|
||||
func (d *Document) newInclude(k Keyword) (int, Node) {
|
||||
resolve := func() Node { panic(fmt.Sprintf("bad include: '#+INCLUDE: %s'", k.Value)) }
|
||||
if m := includeFileRegexp.FindStringSubmatch(k.Value); m != nil {
|
||||
path, kind, lang := m[1], m[2], m[3]
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(filepath.Dir(d.Path), path)
|
||||
}
|
||||
resolve = func() Node {
|
||||
bs, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("bad include '#+INCLUDE: %s': %s", k.Value, err))
|
||||
}
|
||||
return Block{strings.ToUpper(kind), []string{lang}, []Node{Text{string(bs)}}}
|
||||
}
|
||||
}
|
||||
return 1, Include{k, resolve}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue