From b3edd6c18291c37ec7b4758c19f06318f25cd161 Mon Sep 17 00:00:00 2001 From: Niklas Fasching Date: Sun, 11 Apr 2021 21:45:19 +0200 Subject: [PATCH] Improve block parameter parsing The actual parameter parsing logic in emacs org mode is quite complex [1]. All we want for now is to handle parameter values containing spaces [2]. Splitting on ` :` gets us close enough for now. As I'm very opposed to copying 100 lines of parameter parsing logic just to get exports right let's wait for use cases - no hurt in gathering requirements as we go. [1] https://github.com/bzg/org-mode/blob/master/lisp/ob-core.el#L1481 [2] I never ran into such parameters before and wrongly assumed that splitting on spaces would be enough. boy was i wrong - just look at that massive function [1]! that's why we can't have nice things! --- org/block.go | 15 ++++++++++++++- org/testdata/blocks.html | 3 +++ org/testdata/blocks.org | 8 ++++++++ org/testdata/blocks.pretty_org | 8 ++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/org/block.go b/org/block.go index 11b135f..9793f81 100644 --- a/org/block.go +++ b/org/block.go @@ -54,7 +54,7 @@ func isRawTextBlock(name string) bool { return name == "SRC" || name == "EXAMPLE func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) { t, start := d.tokens[i], i - name, parameters := t.content, strings.Fields(t.matches[3]) + name, parameters := t.content, splitParameters(t.matches[3]) trim := trimIndentUpTo(d.tokens[i].lvl) stop := func(d *Document, i int) bool { return i >= len(d.tokens) || (d.tokens[i].kind == "endBlock" && d.tokens[i].content == name) @@ -121,6 +121,19 @@ func trimIndentUpTo(max int) func(string) string { } } +func splitParameters(s string) []string { + parameters, parts := []string{}, strings.Split(s, " :") + lang, rest := strings.TrimSpace(parts[0]), parts[1:] + if lang != "" { + parameters = append(parameters, lang) + } + for _, p := range rest { + kv := strings.SplitN(p+" ", " ", 2) + parameters = append(parameters, ":"+kv[0], strings.TrimSpace(kv[1])) + } + return parameters +} + func (b Block) ParameterMap() map[string]string { if len(b.Parameters) == 0 { return nil diff --git a/org/testdata/blocks.html b/org/testdata/blocks.html index cf1db87..20c7746 100644 --- a/org/testdata/blocks.html +++ b/org/testdata/blocks.html @@ -40,6 +40,9 @@ a source block with results a source block that only exports results
+but the result block is
+
+
 an example block with
 multiple lines including
 
diff --git a/org/testdata/blocks.org b/org/testdata/blocks.org
index b880eea..b4fa908 100644
--- a/org/testdata/blocks.org
+++ b/org/testdata/blocks.org
@@ -38,6 +38,14 @@ echo a source block that only exports results
 #+RESULTS:
 : a source block that only exports results
 
+#+begin_src bash :cmdline -foo -bar :exports results
+# the code block is not rendered
+echo but the result block is
+#+end_src
+
+#+RESULTS:
+: but the result block is
+
 #+BEGIN_EXAMPLE foo bar baz
 an example block with
 multiple lines including
diff --git a/org/testdata/blocks.pretty_org b/org/testdata/blocks.pretty_org
index 8359623..2fade9b 100644
--- a/org/testdata/blocks.pretty_org
+++ b/org/testdata/blocks.pretty_org
@@ -38,6 +38,14 @@ echo a source block that only exports results
 #+RESULTS:
 : a source block that only exports results
 
+#+BEGIN_SRC bash :cmdline -foo -bar :exports results
+# the code block is not rendered
+echo but the result block is
+#+END_SRC
+
+#+RESULTS:
+: but the result block is
+
 #+BEGIN_EXAMPLE foo bar baz
 an example block with
 multiple lines including