From d417c2a6ddcd2ed8b4f0157d96938b65c60d832b Mon Sep 17 00:00:00 2001 From: Niklas Fasching Date: Thu, 16 Apr 2020 15:49:32 +0200 Subject: [PATCH] Implement escaping in src (org only) and example blocks inside src example blocks lines starting with `\s*,` are escaped - i.e. org mode will not try to parse them as e.g. a headline. We don't want to render the escape commata to html so let's take them out - and put them back in before rendering to org. Doing it this way allows us to render them correctly even when the input did not include them. see https://orgmode.org/manual/Literal-Examples.html#Literal-Examples --- org/block.go | 4 ++++ org/org_writer.go | 9 ++++++++- org/testdata/blocks.html | 18 ++++++++++++++++++ org/testdata/blocks.org | 17 +++++++++++++++++ org/testdata/blocks.pretty_org | 19 ++++++++++++++++++- 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/org/block.go b/org/block.go index 78ad9a7..4b88439 100644 --- a/org/block.go +++ b/org/block.go @@ -19,6 +19,7 @@ type Example struct { var exampleLineRegexp = regexp.MustCompile(`^(\s*):(\s(.*)|\s*$)`) var beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`) var endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`) +var exampleBlockEscapeRegexp = regexp.MustCompile(`(^|\n)([ \t]*),([ \t]*)(\*|,\*|#\+|,#\+)`) func lexBlock(line string) (token, bool) { if m := beginBlockRegexp.FindStringSubmatch(line); m != nil { @@ -51,6 +52,9 @@ func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) { for ; !stop(d, i); i++ { rawText += trim(d.tokens[i].matches[0]) + "\n" } + if name == "EXAMPLE" || (name == "SRC" && len(parameters) >= 1 && parameters[0] == "org") { + rawText = exampleBlockEscapeRegexp.ReplaceAllString(rawText, "$1$2$3$4") + } block.Children = d.parseRawInline(rawText) } else { consumed, nodes := d.parseMany(i, stop) diff --git a/org/org_writer.go b/org/org_writer.go index b562cf3..a59461d 100644 --- a/org/org_writer.go +++ b/org/org_writer.go @@ -2,6 +2,7 @@ package org import ( "fmt" + "regexp" "strings" "unicode" "unicode/utf8" @@ -16,6 +17,8 @@ type OrgWriter struct { indent string } +var exampleBlockUnescapeRegexp = regexp.MustCompile(`(^|\n)([ \t]*)(\*|,\*|#\+|,#\+)`) + var emphasisOrgBorders = map[string][]string{ "_": []string{"_", "_"}, "*": []string{"*", "*"}, @@ -90,7 +93,11 @@ func (w *OrgWriter) WriteBlock(b Block) { if isRawTextBlock(b.Name) { w.WriteString(w.indent) } - WriteNodes(w, b.Children...) + content := w.WriteNodesAsString(b.Children...) + if b.Name == "EXAMPLE" || (b.Name == "SRC" && len(b.Parameters) >= 1 && b.Parameters[0] == "org") { + content = exampleBlockUnescapeRegexp.ReplaceAllString(content, "$1$2,$3") + } + w.WriteString(content) if !isRawTextBlock(b.Name) { w.WriteString(w.indent) } diff --git a/org/testdata/blocks.html b/org/testdata/blocks.html index a4da06a..48b7245 100644 --- a/org/testdata/blocks.html +++ b/org/testdata/blocks.html @@ -96,6 +96,24 @@ paragraphs +
+
+
+  #+BEGIN_SRC bash
+  echo src (with language org) and example blocks support escaping using commata
+  #+END_SRC
+
+,* I am not a real headline - commata escape characters aren't renderered
+
+
+
+
+  #+BEGIN_SRC bash
+  echo src (with language org) and example blocks support escaping using commata
+  #+END_SRC
+
+,* I am not a real headline - commata escape characters aren't renderered
+
diff --git a/org/testdata/blocks.org b/org/testdata/blocks.org index b789401..a5b24f5 100644 --- a/org/testdata/blocks.org +++ b/org/testdata/blocks.org @@ -51,6 +51,23 @@ blocks like the quote block parse their content and can contain it can be made visible using css (e.g. =white-space: pre=). #+END_QUOTE +#+BEGIN_SRC org + ,#+BEGIN_SRC bash + echo src (with language org) and example blocks support escaping using commata + ,#+END_SRC + +,,* I am not a real headline - commata escape characters aren't renderered + +#+END_SRC + +#+BEGIN_EXAMPLE + ,#+BEGIN_SRC bash + echo src (with language org) and example blocks support escaping using commata + ,#+END_SRC + +,,* I am not a real headline - commata escape characters aren't renderered +#+END_EXAMPLE + #+BEGIN_EXPORT html