Add basic support for drawers

This commit is contained in:
Niklas Fasching 2018-12-16 23:50:01 +01:00
parent c012b0a533
commit 0186545123
8 changed files with 102 additions and 8 deletions

View file

@ -43,6 +43,7 @@ type token struct {
var lexFns = []lexFn{
lexHeadline,
lexDrawer,
lexBlock,
lexList,
lexTable,
@ -168,6 +169,8 @@ func (d *Document) parseOne(i int, stop stopFn) (consumed int, node Node) {
consumed, node = d.parseTable(i, stop)
case "beginBlock":
consumed, node = d.parseBlock(i, stop)
case "beginDrawer":
consumed, node = d.parseDrawer(i, stop)
case "text":
consumed, node = d.parseParagraph(i, stop)
case "example":

37
org/drawer.go Normal file
View file

@ -0,0 +1,37 @@
package org
import (
"regexp"
"strings"
)
type Drawer struct {
Name string
Children []Node
}
var beginDrawerRegexp = regexp.MustCompile(`^(\s*):(\S+):\s*$`)
var endDrawerRegexp = regexp.MustCompile(`^(\s*):END:\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) {
drawer, start := Drawer{Name: strings.ToUpper(d.tokens[i].content)}, i
i++
stop := func(d *Document, i int) bool {
return parentStop(d, i) || d.tokens[i].kind == "endDrawer" || d.tokens[i].kind == "headline"
}
consumed, nodes := d.parseMany(i, stop)
drawer.Children = nodes
if d.tokens[i+consumed].kind == "endDrawer" {
consumed++
}
return i + consumed - start, drawer
}

View file

@ -7,12 +7,13 @@ import (
)
type Headline struct {
Lvl int
Status string
Priority string
Title []Node
Tags []string
Children []Node
Lvl int
Status string
Priority string
Properties Node
Title []Node
Tags []string
Children []Node
}
var headlineRegexp = regexp.MustCompile(`^([*]+)\s+(.*)`)
@ -60,6 +61,12 @@ func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) {
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].(Drawer); ok && d.Name == "PROPERTIES" {
headline.Properties = d
nodes = nodes[1:]
}
}
headline.Children = nodes
if headline.Lvl == 1 && text == d.Footnotes.Title && d.Footnotes.ExcludeHeading {

View file

@ -74,6 +74,8 @@ func (w *HTMLWriter) writeNodes(ns ...Node) {
w.writeHeadline(n)
case Block:
w.writeBlock(n)
case Drawer:
w.writeDrawer(n)
case FootnoteDefinition:
w.writeFootnoteDefinition(n)
@ -141,6 +143,10 @@ func (w *HTMLWriter) writeBlock(b Block) {
}
}
func (w *HTMLWriter) writeDrawer(d Drawer) {
w.writeNodes(d.Children...)
}
func (w *HTMLWriter) writeKeyword(k Keyword) {
if k.Key == "HTML" {
w.WriteString(k.Value + "\n")

View file

@ -62,6 +62,8 @@ func (w *OrgWriter) writeNodes(ns ...Node) {
w.writeHeadline(n)
case Block:
w.writeBlock(n)
case Drawer:
w.writeDrawer(n)
case FootnoteDefinition:
w.writeFootnoteDefinition(n)
@ -127,6 +129,9 @@ func (w *OrgWriter) writeHeadline(h Headline) {
if len(h.Children) != 0 {
w.WriteString(w.indent)
}
if h.Properties != nil {
w.writeNodes(h.Properties)
}
w.writeNodes(h.Children...)
}
@ -147,6 +152,12 @@ func (w *OrgWriter) writeBlock(b Block) {
w.WriteString(w.indent + "#+END_" + b.Name + "\n")
}
func (w *OrgWriter) writeDrawer(d Drawer) {
w.WriteString(w.indent + ":" + d.Name + ":\n")
w.writeNodes(d.Children...)
w.WriteString(w.indent + ":END:\n")
}
func (w *OrgWriter) writeFootnotes(d *Document) {
fs := d.Footnotes
if len(fs.Definitions) == 0 {

View file

@ -9,6 +9,18 @@ Headline with todo status &amp; priority
<span class="todo">DONE</span>
Headline with TODO status
</h1>
<p>
the <strong>content</strong>
</p>
<h1>
Headline with tags &amp; priority&#xa0;&#xa0;&#xa0;<span class="tags"><span>foo</span>&#xa0;<span>bar</span></span>
</h1>
<p>
Still outside the drawer
</p>
<p>
This is inside the drawer
</p>
<p>
Still outside the drawer
</p>

View file

@ -1,5 +1,14 @@
* Simple Headline
* TODO [#B] Headline with todo status & priority
* DONE Headline with TODO status
* [#A] Headline with tags & priority :foo:bar:
:PROPERTIES:
:Note: property drawers are not exported as html like other drawers
:END:
the *content*
* [#A] Headline with tags & priority :foo:bar:
Still outside the drawer
:DRAWERNAME:
This is inside the drawer
:END:
Still outside the drawer

View file

@ -46,8 +46,17 @@ src block
* Simple Headline
* TODO [#B] Headline with todo status &amp; priority
* DONE Headline with TODO status
* [#A] Headline with tags &amp; priority :foo:bar:
:PROPERTIES:
:Note: property drawers are not exported as html like other drawers
:END:
the *content*
* [#A] Headline with tags &amp; priority :foo:bar:
Still outside the drawer
:DRAWERNAME:
This is inside the drawer
:END:
Still outside the drawer
</pre>
</div>