diff --git a/org/block.go b/org/block.go index 9793f81..2f30a7a 100644 --- a/org/block.go +++ b/org/block.go @@ -1,6 +1,7 @@ package org import ( + "math" "regexp" "strings" "unicode" @@ -21,9 +22,15 @@ type Example struct { Children []Node } +type LatexBlock struct { + Content []Node +} + var exampleLineRegexp = regexp.MustCompile(`^(\s*):(\s(.*)|\s*$)`) var beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`) var endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`) +var beginLatexBlockRegexp = regexp.MustCompile(`(?i)^(\s*)\\begin{([^}]+)}(\s*)$`) +var endLatexBlockRegexp = regexp.MustCompile(`(?i)^(\s*)\\end{([^}]+)}(\s*)$`) var resultRegexp = regexp.MustCompile(`(?i)^(\s*)#\+RESULTS:`) var exampleBlockEscapeRegexp = regexp.MustCompile(`(^|\n)([ \t]*),([ \t]*)(\*|,\*|#\+|,#\+)`) @@ -36,6 +43,15 @@ func lexBlock(line string) (token, bool) { return nilToken, false } +func lexLatexBlock(line string) (token, bool) { + if m := beginLatexBlockRegexp.FindStringSubmatch(line); m != nil { + return token{"beginLatexBlock", len(m[1]), strings.ToUpper(m[2]), m}, true + } else if m := endLatexBlockRegexp.FindStringSubmatch(line); m != nil { + return token{"endLatexBlock", len(m[1]), strings.ToUpper(m[2]), m}, true + } + return nilToken, false +} + func lexResult(line string) (token, bool) { if m := resultRegexp.FindStringSubmatch(line); m != nil { return token{"result", len(m[1]), "", m}, true @@ -85,6 +101,22 @@ func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) { return i + 1 - start, block } +func (d *Document) parseLatexBlock(i int, parentStop stopFn) (int, Node) { + t, start := d.tokens[i], i + name, rawText, trim := t.content, "", trimIndentUpTo(int(math.Max((float64(d.baseLvl)), float64(t.lvl)))) + stop := func(d *Document, i int) bool { + return i >= len(d.tokens) || (d.tokens[i].kind == "endLatexBlock" && d.tokens[i].content == name) + } + for ; !stop(d, i); i++ { + rawText += trim(d.tokens[i].matches[0]) + "\n" + } + if i >= len(d.tokens) || d.tokens[i].kind != "endLatexBlock" || d.tokens[i].content != name { + return 0, nil + } + rawText += trim(d.tokens[i].matches[0]) + return i + 1 - start, LatexBlock{d.parseRawInline(rawText)} +} + func (d *Document) parseSrcBlockResult(i int, parentStop stopFn) (int, Node) { start := i for ; !parentStop(d, i) && d.tokens[i].kind == "text" && d.tokens[i].content == ""; i++ { @@ -145,6 +177,7 @@ func (b Block) ParameterMap() map[string]string { return m } -func (n Example) String() string { return orgWriter.WriteNodesAsString(n) } -func (n Block) String() string { return orgWriter.WriteNodesAsString(n) } -func (n Result) String() string { return orgWriter.WriteNodesAsString(n) } +func (n Example) String() string { return orgWriter.WriteNodesAsString(n) } +func (n Block) String() string { return orgWriter.WriteNodesAsString(n) } +func (n LatexBlock) String() string { return orgWriter.WriteNodesAsString(n) } +func (n Result) String() string { return orgWriter.WriteNodesAsString(n) } diff --git a/org/document.go b/org/document.go index 755864b..9da27b9 100644 --- a/org/document.go +++ b/org/document.go @@ -72,6 +72,7 @@ var lexFns = []lexFn{ lexKeywordOrComment, lexFootnoteDefinition, lexExample, + lexLatexBlock, lexText, } @@ -209,6 +210,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 "beginLatexBlock": + consumed, node = d.parseLatexBlock(i, stop) case "result": consumed, node = d.parseResult(i, stop) case "beginDrawer": diff --git a/org/html_writer.go b/org/html_writer.go index 28c402c..5918af6 100644 --- a/org/html_writer.go +++ b/org/html_writer.go @@ -162,6 +162,11 @@ func (w *HTMLWriter) WriteBlock(b Block) { } } +func (w *HTMLWriter) WriteLatexBlock(b LatexBlock) { + WriteNodes(w, b.Content...) + w.WriteString("\n") +} + func (w *HTMLWriter) WriteResult(r Result) { WriteNodes(w, r.Node) } func (w *HTMLWriter) WriteInlineBlock(b InlineBlock) { diff --git a/org/org_writer.go b/org/org_writer.go index 0cfaead..fce6d20 100644 --- a/org/org_writer.go +++ b/org/org_writer.go @@ -109,6 +109,12 @@ func (w *OrgWriter) WriteBlock(b Block) { } } +func (w *OrgWriter) WriteLatexBlock(b LatexBlock) { + w.WriteString(w.indent) + WriteNodes(w, b.Content...) + w.WriteString("\n") +} + func (w *OrgWriter) WriteResult(r Result) { w.WriteString("#+RESULTS:\n") WriteNodes(w, r.Node) diff --git a/org/testdata/latex.html b/org/testdata/latex.html index 58bbb8a..8659467 100644 --- a/org/testdata/latex.html +++ b/org/testdata/latex.html @@ -6,8 +6,18 @@ we support \(...\), \[...\]
  • \[\sum_{i=1}^n a_n\]
  • $$\sum_{i=1}^n a_n$$
  • \begin{xyz}\sum_{i=1}^n a_n\end{xyz}
  • -
  • \begin{xyz} +
  • +\begin{xyz} \sum_{i=1}^n a_n -\end{xyz}
  • +\end{xyz} +
  • $2 + 2$, $3 - 3$
  • +
  • +\begin{xyz} +latex block ignores block lvl elements (e.g. list - line starting with -) +a = b +- c +- d +\end{xyz} +
  • diff --git a/org/testdata/latex.org b/org/testdata/latex.org index 5a4c953..534d026 100644 --- a/org/testdata/latex.org +++ b/org/testdata/latex.org @@ -10,3 +10,9 @@ we support =\(...\)=, =\[...\]=, =$$...$$= and =\begin{$env}...\end{$env}= as la \sum_{i=1}^n a_n \end{xyz} - $2 + 2$, $3 - 3$ +- \begin{xyz} + latex block ignores block lvl elements (e.g. list - line starting with -) + a = b + - c + - d + \end{xyz} diff --git a/org/testdata/latex.pretty_org b/org/testdata/latex.pretty_org index 5a4c953..534d026 100644 --- a/org/testdata/latex.pretty_org +++ b/org/testdata/latex.pretty_org @@ -10,3 +10,9 @@ we support =\(...\)=, =\[...\]=, =$$...$$= and =\begin{$env}...\end{$env}= as la \sum_{i=1}^n a_n \end{xyz} - $2 + 2$, $3 - 3$ +- \begin{xyz} + latex block ignores block lvl elements (e.g. list - line starting with -) + a = b + - c + - d + \end{xyz} diff --git a/org/writer.go b/org/writer.go index 29b64bd..fb918e8 100644 --- a/org/writer.go +++ b/org/writer.go @@ -19,6 +19,7 @@ type Writer interface { WriteHeadline(Headline) WriteBlock(Block) WriteResult(Result) + WriteLatexBlock(LatexBlock) WriteInlineBlock(InlineBlock) WriteExample(Example) WriteDrawer(Drawer) @@ -62,6 +63,8 @@ func WriteNodes(w Writer, nodes ...Node) { w.WriteBlock(n) case Result: w.WriteResult(n) + case LatexBlock: + w.WriteLatexBlock(n) case InlineBlock: w.WriteInlineBlock(n) case Example: