Implement #+MACRO
This commit is contained in:
parent
2ab65d300a
commit
9f7e8a8fbd
9 changed files with 55 additions and 0 deletions
|
@ -36,6 +36,7 @@ type Document struct {
|
||||||
Path string // Path of the file containing the parse input - used to resolve relative paths during parsing (e.g. INCLUDE).
|
Path string // Path of the file containing the parse input - used to resolve relative paths during parsing (e.g. INCLUDE).
|
||||||
tokens []token
|
tokens []token
|
||||||
baseLvl int
|
baseLvl int
|
||||||
|
Macros map[string]string
|
||||||
Links map[string]string
|
Links map[string]string
|
||||||
Nodes []Node
|
Nodes []Node
|
||||||
NamedNodes map[string]Node
|
NamedNodes map[string]Node
|
||||||
|
@ -123,6 +124,7 @@ func (c *Configuration) Parse(input io.Reader, path string) (d *Document) {
|
||||||
BufferSettings: map[string]string{},
|
BufferSettings: map[string]string{},
|
||||||
NamedNodes: map[string]Node{},
|
NamedNodes: map[string]Node{},
|
||||||
Links: map[string]string{},
|
Links: map[string]string{},
|
||||||
|
Macros: map[string]string{},
|
||||||
Path: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
|
@ -355,6 +355,19 @@ func (w *HTMLWriter) WriteRegularLink(l RegularLink) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *HTMLWriter) WriteMacro(m Macro) {
|
||||||
|
if macro := w.document.Macros[m.Name]; macro != "" {
|
||||||
|
for i, param := range m.Parameters {
|
||||||
|
macro = strings.Replace(macro, fmt.Sprintf("$%d", i+1), param, -1)
|
||||||
|
}
|
||||||
|
macroDocument := w.document.Parse(strings.NewReader(macro), w.document.Path)
|
||||||
|
if macroDocument.Error != nil {
|
||||||
|
w.log.Printf("bad macro: %s -> %s: %v", m.Name, macro, macroDocument.Error)
|
||||||
|
}
|
||||||
|
WriteNodes(w, macroDocument.Nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) WriteList(l List) {
|
func (w *HTMLWriter) WriteList(l List) {
|
||||||
tags, ok := listTags[l.Kind]
|
tags, ok := listTags[l.Kind]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -54,6 +54,11 @@ type RegularLink struct {
|
||||||
AutoLink bool
|
AutoLink bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Macro struct {
|
||||||
|
Name string
|
||||||
|
Parameters []string
|
||||||
|
}
|
||||||
|
|
||||||
var validURLCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;="
|
var validURLCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;="
|
||||||
var autolinkProtocols = regexp.MustCompile(`^(https?|ftp|file)$`)
|
var autolinkProtocols = regexp.MustCompile(`^(https?|ftp|file)$`)
|
||||||
var imageExtensionRegexp = regexp.MustCompile(`^[.](png|gif|jpe?g|svg|tiff?)$`)
|
var imageExtensionRegexp = regexp.MustCompile(`^[.](png|gif|jpe?g|svg|tiff?)$`)
|
||||||
|
@ -66,6 +71,7 @@ var statisticsTokenRegexp = regexp.MustCompile(`^\[(\d+/\d+|\d+%)\]`)
|
||||||
var latexFragmentRegexp = regexp.MustCompile(`(?s)^\\begin{(\w+)}(.*)\\end{(\w+)}`)
|
var latexFragmentRegexp = regexp.MustCompile(`(?s)^\\begin{(\w+)}(.*)\\end{(\w+)}`)
|
||||||
var inlineBlockRegexp = regexp.MustCompile(`src_(\w+)(\[(.*)\])?{(.*)}`)
|
var inlineBlockRegexp = regexp.MustCompile(`src_(\w+)(\[(.*)\])?{(.*)}`)
|
||||||
var inlineExportBlockRegexp = regexp.MustCompile(`@@(\w+):(.*?)@@`)
|
var inlineExportBlockRegexp = regexp.MustCompile(`@@(\w+):(.*?)@@`)
|
||||||
|
var macroRegexp = regexp.MustCompile(`{{{(.*)\((.*)\)}}}`)
|
||||||
|
|
||||||
var timestampFormat = "2006-01-02 Mon 15:04"
|
var timestampFormat = "2006-01-02 Mon 15:04"
|
||||||
var datestampFormat = "2006-01-02 Mon"
|
var datestampFormat = "2006-01-02 Mon"
|
||||||
|
@ -94,6 +100,8 @@ func (d *Document) parseInline(input string) (nodes []Node) {
|
||||||
consumed, node = d.parseEmphasis(input, current, true)
|
consumed, node = d.parseEmphasis(input, current, true)
|
||||||
case '[':
|
case '[':
|
||||||
consumed, node = d.parseOpeningBracket(input, current)
|
consumed, node = d.parseOpeningBracket(input, current)
|
||||||
|
case '{':
|
||||||
|
consumed, node = d.parseMacro(input, current)
|
||||||
case '<':
|
case '<':
|
||||||
consumed, node = d.parseTimestamp(input, current)
|
consumed, node = d.parseTimestamp(input, current)
|
||||||
case '\\':
|
case '\\':
|
||||||
|
@ -238,6 +246,13 @@ func (d *Document) parseOpeningBracket(input string, start int) (int, Node) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Document) parseMacro(input string, start int) (int, Node) {
|
||||||
|
if m := macroRegexp.FindStringSubmatch(input[start:]); m != nil {
|
||||||
|
return len(m[0]), Macro{m[1], strings.Split(m[2], ",")}
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Document) parseFootnoteReference(input string, start int) (int, Node) {
|
func (d *Document) parseFootnoteReference(input string, start int) (int, Node) {
|
||||||
if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil {
|
if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil {
|
||||||
name, definition := m[1], m[3]
|
name, definition := m[1], m[3]
|
||||||
|
@ -389,4 +404,5 @@ func (n InlineBlock) String() string { return orgWriter.WriteNodesAsString
|
||||||
func (n LatexFragment) String() string { return orgWriter.WriteNodesAsString(n) }
|
func (n LatexFragment) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||||
func (n FootnoteLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
func (n FootnoteLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||||
func (n RegularLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
func (n RegularLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||||
|
func (n Macro) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||||
func (n Timestamp) String() string { return orgWriter.WriteNodesAsString(n) }
|
func (n Timestamp) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||||
|
|
|
@ -67,6 +67,11 @@ func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) {
|
||||||
d.Links[parts[0]] = parts[1]
|
d.Links[parts[0]] = parts[1]
|
||||||
}
|
}
|
||||||
return 1, k
|
return 1, k
|
||||||
|
case "MACRO":
|
||||||
|
if parts := strings.Split(k.Value, " "); len(parts) >= 2 {
|
||||||
|
d.Macros[parts[0]] = parts[1]
|
||||||
|
}
|
||||||
|
return 1, k
|
||||||
case "CAPTION", "ATTR_HTML":
|
case "CAPTION", "ATTR_HTML":
|
||||||
consumed, node := d.parseAffiliated(i, stop)
|
consumed, node := d.parseAffiliated(i, stop)
|
||||||
if consumed != 0 {
|
if consumed != 0 {
|
||||||
|
|
|
@ -360,3 +360,7 @@ func (w *OrgWriter) WriteRegularLink(l RegularLink) {
|
||||||
w.WriteString(fmt.Sprintf("[[%s][%s]]", l.URL, w.WriteNodesAsString(l.Description...)))
|
w.WriteString(fmt.Sprintf("[[%s][%s]]", l.URL, w.WriteNodesAsString(l.Description...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *OrgWriter) WriteMacro(m Macro) {
|
||||||
|
w.WriteString(fmt.Sprintf("{{{%s(%s)}}}", m.Name, strings.Join(m.Parameters, ",")))
|
||||||
|
}
|
||||||
|
|
8
org/testdata/inline.html
vendored
8
org/testdata/inline.html
vendored
|
@ -168,6 +168,14 @@ timestamps
|
||||||
<li>
|
<li>
|
||||||
<p>
|
<p>
|
||||||
<code class="verbatim">#+LINK</code> based links: <a href="https://www.example.com/foobar">https://www.example.com/foobar</a>
|
<code class="verbatim">#+LINK</code> based links: <a href="https://www.example.com/foobar">https://www.example.com/foobar</a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<code class="verbatim">#+MACROs</code>: <p>
|
||||||
|
<h1>yolo</h1>
|
||||||
|
</p>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
2
org/testdata/inline.org
vendored
2
org/testdata/inline.org
vendored
|
@ -39,3 +39,5 @@
|
||||||
- <2019-01-06 18:00 +1w>
|
- <2019-01-06 18:00 +1w>
|
||||||
- =#+LINK= based links: [[example:foobar]]
|
- =#+LINK= based links: [[example:foobar]]
|
||||||
#+LINK: example https://www.example.com/
|
#+LINK: example https://www.example.com/
|
||||||
|
- =#+MACROs=: {{{headline(yolo)}}}
|
||||||
|
#+MACRO: headline @@html:<h1>$1</h1>@@
|
||||||
|
|
2
org/testdata/inline.pretty_org
vendored
2
org/testdata/inline.pretty_org
vendored
|
@ -39,3 +39,5 @@
|
||||||
- <2019-01-06 Sun 18:00 +1w>
|
- <2019-01-06 Sun 18:00 +1w>
|
||||||
- =#+LINK= based links: [[example:foobar]]
|
- =#+LINK= based links: [[example:foobar]]
|
||||||
#+LINK: example https://www.example.com/
|
#+LINK: example https://www.example.com/
|
||||||
|
- =#+MACROs=: {{{headline(yolo)}}}
|
||||||
|
#+MACRO: headline @@html:<h1>$1</h1>@@
|
||||||
|
|
|
@ -36,6 +36,7 @@ type Writer interface {
|
||||||
WriteExplicitLineBreak(ExplicitLineBreak)
|
WriteExplicitLineBreak(ExplicitLineBreak)
|
||||||
WriteLineBreak(LineBreak)
|
WriteLineBreak(LineBreak)
|
||||||
WriteRegularLink(RegularLink)
|
WriteRegularLink(RegularLink)
|
||||||
|
WriteMacro(Macro)
|
||||||
WriteTimestamp(Timestamp)
|
WriteTimestamp(Timestamp)
|
||||||
WriteFootnoteLink(FootnoteLink)
|
WriteFootnoteLink(FootnoteLink)
|
||||||
WriteFootnoteDefinition(FootnoteDefinition)
|
WriteFootnoteDefinition(FootnoteDefinition)
|
||||||
|
@ -95,6 +96,8 @@ func WriteNodes(w Writer, nodes ...Node) {
|
||||||
w.WriteLineBreak(n)
|
w.WriteLineBreak(n)
|
||||||
case RegularLink:
|
case RegularLink:
|
||||||
w.WriteRegularLink(n)
|
w.WriteRegularLink(n)
|
||||||
|
case Macro:
|
||||||
|
w.WriteMacro(n)
|
||||||
case Timestamp:
|
case Timestamp:
|
||||||
w.WriteTimestamp(n)
|
w.WriteTimestamp(n)
|
||||||
case FootnoteLink:
|
case FootnoteLink:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue