On Fri, 16 Jan 2015, Nicolas Goaziou wrote:

"Charles C. Berry" <ccbe...@ucsd.edu> writes:

I've attached three patches and two files that show the behavior under
the current master (12 Jan 2015,
e0879b03d08bb4acc663084076370482f61e8698) and under the patched
version.

Thank you. Some comments follow.


[snip]


I don't think inline Babel blocks should be able to generate lists or
tables. Org cannot contain inline lists or tables. If you need a real
table or list, a regular Babel call will do.

I suggest to ignore :results table and :results list, or even return an
error, since this is bound to breaking the document structure.


OK. Now those cases (and some others) insert `*Inline error:' and a
comment as to what the error is and ignore the actual value.

Based on my own experience, I thought it best to allow Babel to run without stopping when there are problems with inline src blocks rather than stop with an error.

[snip]


I think the "protect commas and backslashes commas" should be factored
out of "ob-core.el" (and "org-element.el") and moved into
"org-macro.el".


OK.

I hope the approach I took modifies `org-macro-expand'.

The "as-is" template returns the macro element :value stripped of the leading "{{{<name>(" and the trailing "[\n]?)}}}". The template allows macros that mark text - possibly including commas - but do not modify it.

I am not sure why you mentioned org-element.el.

[snip]

Other comments from Nicolas 16 Jan email are addresed in the attached patches.

These patches address inline babel calls and apply the same logic to them.

A file with examples is attached.

n.b. the patch prefix numbers are 0002-0005.

HTH,

Chuck
From 28e91c6dc718bef24b2e960864f458da046df225 Mon Sep 17 00:00:00 2001
From: chasberry <ccbe...@ucsd.edu>
Date: Thu, 13 Nov 2014 20:45:01 -0800
Subject: [PATCH 2/5] lisp/ob-core.el: Inline source block / babel call results
 are replaceable

 * lisp/ob-core.el (org-babel-insert-result): Delete any `results'
   macro following current inline src block; insert current value in
   'results' macro possibly wrapping RESULT in an export snippet or
   inline source block first.

  * lisp/ob-core.el (org-babel-remove-inline-result): Delete results
     of current inline src block or inline babel call if it is wrapped
     in a "{{{results(.*)}}}" macro call.

* lisp/ob-core.el (org-babel-get-lob-one-liner-matches): Ensure that
  the point ends up on the same line as, and just before, `call_' when
  searching backward.

Inline source block or babel call results can be removed by
re-executing the source blocks or babel calls if they are wrapped in a
`{{{results(...)}}}' macro.  The schema for the RESULT-PARAMS is:

  |-----------------+--------------------------------------------------|
  | Param           | Example output                                   |
  |-----------------+--------------------------------------------------|
  | default/replace | {{{results(42)}}}                                |
  | raw             | 42                                               |
  | drawer          | {{{results(42)}}}                                |
  | org             | {{{results(src_org{...})}}}                      |
  | html            | {{{results(@@html:...@@)}}}                      |
  | latex           | {{{results(@@latex:...@@)}}}                     |
  | code            | {{{results(src_xxx{...})}}}                      |
  | file            | {{{results([[file:something.pdf]])}}}            |
  | table           | {{{results(*Inline error:* `:results table')}}}  |
  | list            | {{{results(*Inline error:* `:results list')}}}   |
  |-----------------+--------------------------------------------------|

 where the default is `src_emacs{42}' and subsequent rows give the `:results' 
arg.

The `:wrap something' header arg gives an effect similar to `:results
 html' or `:results latex'.

Results that are lists or tables or strings with more than one line
(excepting a trailing "\n") output *Inline error:* messages wrapped in
the `results' macro.

On export, the `results' macro is stripped away before the buffer is
parsed.
---
 lisp/ob-core.el | 116 +++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 85 insertions(+), 31 deletions(-)

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 93fcb2a..63ccabc 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -251,7 +251,8 @@ Returns non-nil if match-data set"
 Returns non-nil if match-data set"
   (save-excursion
     (unless (= (point) (point-at-bol)) ;; move before inline block
-      (re-search-backward "[ \f\t\n\r\v]" nil t))
+      (re-search-backward "\\([^[:alpha:]]\\|[ \f\t\n\r\v]\\)call_" nil t)
+      (goto-char (match-end 1)))
     (if (looking-at org-babel-inline-lob-one-liner-regexp)
        t
       nil)))
@@ -2073,13 +2074,18 @@ If the path of the link is a file path it is expanded 
using
 (defun org-babel-insert-result
   (result &optional result-params info hash indent lang)
   "Insert RESULT into the current buffer.
-By default RESULT is inserted after the end of the
-current source block.  With optional argument RESULT-PARAMS
-controls insertion of results in the org-mode file.
+By default RESULT is inserted after the end of the current source
+block.  The RESULT of an inline source block usually will be
+wrapped inside a `results' macro and placed on the same line as
+the inline source block.  The macro is stripped upon
+export.  Multiline and non-scalar RESULTS from inline source
+blocks are fragile and should be avoided. With optional argument
+RESULT-PARAMS controls insertion of results in the Org mode file.
 RESULT-PARAMS can take the following values:
 
 replace - (default option) insert results after the source block
-          replacing any previously inserted results
+          or inline source block replacing any previously
+          inserted results
 
 silent -- no results are inserted into the Org-mode buffer but
           the results are echoed to the minibuffer and are
@@ -2096,8 +2102,9 @@ raw ----- results are added directly to the Org-mode 
file.  This
           formatted text.
 
 drawer -- results are added directly to the Org-mode file as with
-          \"raw\", but are wrapped in a RESULTS drawer, allowing
-          them to later be replaced or removed automatically.
+          \"raw\", but are wrapped in a RESULTS drawer or results
+          macro, allowing them to later be replaced or removed
+          automatically.
 
 org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC
           org\" block depending on whether the current source block is
@@ -2105,13 +2112,15 @@ org ----- results are added inside of a \"src_org{}\" 
or \"#+BEGIN_SRC
           but Org syntax here will be discarded when exporting the
           file.
 
-html ---- results are added inside of a #+BEGIN_HTML block.  This
-          is a good option if you code block will output html
-          formatted text.
+html ---- results are added inside of a #+BEGIN_HTML block or
+          html export snippet depending on whether the current
+          source block is inline or not.  This is a good option
+          if you code block will output html formatted text.
 
-latex --- results are added inside of a #+BEGIN_LATEX block.
-          This is a good option if you code block will output
-          latex formatted text.
+latex --- results are added inside of a #+BEGIN_LATEX block or
+          latex export snippet depending on whether the current
+          source block is inline or not.  This is a good option
+          if you code block will output latex formatted text.
 
 code ---- the results are extracted in the syntax of the source
           code of the language being evaluated and are added
@@ -2138,11 +2147,20 @@ code ---- the results are extracted in the syntax of 
the source
                (when (or (org-babel-get-inline-src-block-matches)
                          (org-babel-get-lob-one-liner-matches))
                  (goto-char (match-end 0))
-                 (insert (if (listp result) "\n" " "))
+                 (insert " ")
                  (point))))
-            (existing-result (unless inlinep
+            (existing-result (if inlinep
+                                 (org-babel-remove-inline-result)
                                (org-babel-where-is-src-block-result
                                 t info hash indent)))
+            (bad-inline-p
+             (when inlinep
+               (or
+                (and (member "table" result-params) "`:results table'")
+                (and (listp result) "list result")
+                (and (string-match-p "\n.+" result) "multiline result")
+                (and (member "list" result-params) "`:results list'")
+                )))
             (results-switches
              (cdr (assoc :results_switches (nth 2 info))))
             (visible-beg (copy-marker (point-min)))
@@ -2179,7 +2197,12 @@ code ---- the results are extracted in the syntax of the 
source
                 ((member "prepend" result-params)))) ; already there
              (setq results-switches
                    (if results-switches (concat " " results-switches) ""))
-             (let ((wrap (lambda (start finish &optional no-escape no-newlines)
+             (let ((wrap (lambda (start finish &optional no-escape no-newlines
+                                        inline-start inline-finish)
+                           (when inlinep
+                             (setq start inline-start)
+                             (setq finish inline-finish)
+                             (setq no-newlines t))
                            (goto-char end)
                            (insert (concat finish (unless no-newlines "\n")))
                            (goto-char beg)
@@ -2194,8 +2217,13 @@ code ---- the results are extracted in the syntax of the 
source
                (cond
                 ;; do nothing for an empty result
                 ((null result))
+                ;; illegal inline result or params
+                (bad-inline-p
+                 (goto-char beg)
+                 (insert "{{{results(*Inline error:* " bad-inline-p ")}}}" ))
                 ;; insert a list if preferred
                 ((member "list" result-params)
+                 (goto-char beg)
                  (insert
                   (org-babel-trim
                    (org-list-to-generic
@@ -2225,37 +2253,45 @@ code ---- the results are extracted in the syntax of 
the source
                (setq end (point-marker))
                ;; possibly wrap result
                (cond
+                (bad-inline-p) ;; do nothing
                 ((assoc :wrap (nth 2 info))
                  (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS")))
                    (funcall wrap (concat "#+BEGIN_" name)
-                            (concat "#+END_" (car (org-split-string name))))))
+                            (concat "#+END_" (car (org-split-string name)))
+                            nil nil (concat "{{{results(@@" name ":") 
"@@)}}}")))
                 ((member "html" result-params)
-                 (funcall wrap "#+BEGIN_HTML" "#+END_HTML"))
-                ((member "latex" result-params)
-                 (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX"))
+                 (funcall wrap "#+BEGIN_HTML" "#+END_HTML" nil nil
+                          "{{{results(@@html:" "@@)}}}"))
+                ((member "latex" result-params) 
+                 (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX" nil nil
+                          "{{{results(@@latex:" "@@)}}}"))
                 ((member "org" result-params)
                  (goto-char beg) (if (org-at-table-p) (org-cycle))
-                 (if inlinep
-                     (funcall wrap "src_org{" "}" nil t)
-                     (funcall wrap "#+BEGIN_SRC org" "#+END_SRC")))
+                 (funcall wrap "#+BEGIN_SRC org" "#+END_SRC" nil nil
+                          "{{{results(src_org{" "})}}}"))
                 ((member "code" result-params)
                  (let ((lang (or lang "none")))
-                   (if inlinep
-                       (funcall wrap (format "src_%s[%s]{" lang 
results-switches)
-                                "}" nil t)
-                       (funcall wrap (format "#+BEGIN_SRC %s%s" lang 
results-switches)
-                                "#+END_SRC"))))
+                   (funcall wrap (format "#+BEGIN_SRC %s%s" lang 
results-switches)
+                            "#+END_SRC" nil nil
+                            (format "{{{results(src_%s[%s]{" lang 
results-switches)
+                            "})}}}")))
                 ((member "raw" result-params)
                  (goto-char beg) (if (org-at-table-p) (org-cycle)))
                 ((or (member "drawer" result-params)
                      ;; Stay backward compatible with <7.9.2
                      (member "wrap" result-params))
                  (goto-char beg) (if (org-at-table-p) (org-cycle))
-                 (funcall wrap ":RESULTS:" ":END:" 'no-escape))
+                 (funcall wrap ":RESULTS:" ":END:" 'no-escape nil
+                          "{{{results(" ")}}}"))
+                ((and inlinep (member "file" result-params))
+                 (funcall wrap nil nil nil nil "{{{results(" ")}}}"))
                 ((and (not (funcall proper-list-p result))
                       (not (member "file" result-params)))
-                 (org-babel-examplify-region beg end results-switches)
-                 (setq end (point)))))
+                 (let ((org-babel-inline-result-wrap
+                        ;; Hard code {{{results(...)}}} on top of 
customization.
+                        (format "{{{results(%s)}}}" 
org-babel-inline-result-wrap)))
+                   (org-babel-examplify-region beg end results-switches)
+                   (setq end (point))))))
              ;; possibly indent the results to match the #+results line
              (when (and (not inlinep) (numberp indent) indent (> indent 0)
                         ;; in this case `table-align' does the work for us
@@ -2283,6 +2319,24 @@ code ---- the results are extracted in the syntax of the 
source
           (if keep-keyword (1+ (match-end 0)) (1- (match-beginning 0)))
           (progn (forward-line 1) (org-babel-result-end))))))))
 
+(defun org-babel-remove-inline-result ()
+  "Remove the result of the current inline-src-block.
+The result must be wrapped in a `results' macro to be
+  removed. Extraneous leading whitespace is trimmed."
+  (let* ((el (org-element-context))
+        (post-blank (org-element-property :post-blank el)))
+    (when (member (org-element-type el) '(inline-src-block inline-babel-call))
+      (org-with-wide-buffer
+        (goto-char (org-element-property :end el))
+        (let  ((el (org-element-context)))
+         (when (and (eq (org-element-type el) 'macro)
+                    (string= (org-element-property :key el) "results"))
+           (delete-region ; And (only) extra leading whitespace.
+            (- (org-element-property :begin el)
+               (- post-blank 1))
+            (- (org-element-property :end el)
+               (org-element-property :post-blank el)))))))))
+
 (defun org-babel-remove-result-one-or-many (x)
   "Remove the result of the current source block.
 If called with a prefix argument, remove all result blocks
-- 
1.9.3 (Apple Git-50)

From 6bc9acb7376ea16fe149bf4749fa56387ce526cf Mon Sep 17 00:00:00 2001
From: chasberry <ccbe...@ucsd.edu>
Date: Thu, 13 Nov 2014 20:49:57 -0800
Subject: [PATCH 3/5] ob-exp.el: Enable removal of {{{results(...)}}}

* ob-exp.el (org-babel-do-export): `clean' lambda form removes inline
  results wrapped in `results{{{(' `)}}}' by calling
  `org-babel-remove-inline-result'.
---
 lisp/ob-exp.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index edb889c..afe6cd9 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -315,7 +315,9 @@ The function respects the value of the :exports header 
argument."
   (let ((silently (lambda () (let ((session (cdr (assoc :session (nth 2 
info)))))
                               (when (not (and session (equal "none" session)))
                                 (org-babel-exp-results info type 'silent)))))
-       (clean (lambda () (unless (eq type 'inline) (org-babel-remove-result 
info)))))
+       (clean (lambda () (if (eq type 'inline)
+                             (org-babel-remove-inline-result info)
+                           (org-babel-remove-result info)))))
     (case (intern (or (cdr (assoc :exports (nth 2 info))) "code"))
       ('none (funcall silently) (funcall clean) "")
       ('code (funcall silently) (funcall clean) (org-babel-exp-code info type))
-- 
1.9.3 (Apple Git-50)

From 66b61c0e68af63f41f52c37a3ee9bc5488670889 Mon Sep 17 00:00:00 2001
From: chasberry <ccbe...@ucsd.edu>
Date: Thu, 13 Nov 2014 20:55:36 -0800
Subject: [PATCH 4/5] lisp/ox.el: Enable removable inline src results

* lisp/ox.el: (org-export-as): Treat `results' as an `identity' macro
  with one argument - possibly including commas - after Babel executes.
---
 lisp/ox.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lisp/ox.el b/lisp/ox.el
index 8880e10..1e85a36 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -2884,7 +2884,8 @@ Return code as a string."
                ;; EMAIL is not a parsed keyword: store it as-is.
                (cons "email" (or (plist-get info :email) ""))
                (cons "title"
-                     (org-element-interpret-data (plist-get info :title))))
+                     (org-element-interpret-data (plist-get info :title)))
+               (cons "results" "as-is"))
          'finalize)
         ;; Parse buffer.
         (setq tree (org-element-parse-buffer nil visible-only))
-- 
1.9.3 (Apple Git-50)

From a879760d52cdaa235dcb3ef3ee601643ae8d4fe2 Mon Sep 17 00:00:00 2001
From: chasberry <ccbe...@ucsd.edu>
Date: Sun, 18 Jan 2015 16:27:31 -0800
Subject: [PATCH 5/5] org-macro.el: Implement an `identity' macro

* lisp/org-macro.el (org-macro-expand): The "as-is" template returns
  the macro element :value stripped of the leading "{{{<name>(" and
  the trailing "[\n]?)}}}".  The template allows macros that mark text
  - possibly including commas - but do not modify it.
---
 lisp/org-macro.el | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/lisp/org-macro.el b/lisp/org-macro.el
index 923e377..8e8614b 100644
--- a/lisp/org-macro.el
+++ b/lisp/org-macro.el
@@ -150,10 +150,15 @@ default value.  Return nil if no template was found."
                           ""))
                     template nil 'literal)))
         ;; VALUE starts with "(eval": it is a s-exp, `eval' it.
-        (when (string-match "\\`(eval\\>" value)
+        (cond
+        ((string-match "\\`(eval\\>" value)
           (setq value (eval (read value))))
+        ((string= "as-is" value)
+         (setq value (replace-regexp-in-string
+                      "^{{{[[:alpha:]]+(\\(.*\\)\n?)}}}$" "\\1"
+                      (org-element-property :value macro)))))
         ;; Return string.
-        (format "%s" (or value ""))))))
+       (format "%s" (or value ""))))))
 
 (defun org-macro-replace-all (templates &optional finalize)
   "Replace all macros in current buffer by their expansion.
-- 
1.9.3 (Apple Git-50)

Demonstrate inline-src block-behavior and the {{{results( )}}} macro.

The `demo' src block sets up an inline-src-block, calls it, then
exports the result. The output is as follows:

- inline-src-block :: inline-src-block with headers and content.
- export backend :: Which backend was used to render the result.
- result :: What the ~*.org~ buffer looks looks like after babel
     executes the inline-src-block.
- exported as :: Show the exported version (starting on the next line). 

* :results replace (default) 

#+name: demo
#+BEGIN_SRC emacs-lisp :var str="replace" bkend="ascii" contents="42"
  (let ((cmd (format "src_emacs-lisp[:results %s]{%s}" str contents)))
    (concat "inline-src-block: " cmd "\nexport backend: " bkend 
            "\nresult: " (with-temp-buffer
                           (insert cmd)
                           (org-babel-execute-buffer)
                           (buffer-string))
            "\nexported as:\n"
            (org-export-string-as cmd (intern bkend) t)))
#+END_SRC

#+RESULTS: demo
: inline-src-block: src_emacs-lisp[:results replace]{42}
: export backend: ascii
: result: src_emacs-lisp[:results replace]{42} {{{results(=42=)}}}
: exported as:
: `42'


#+CALL: demo("replace")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results replace]{42}
: export backend: ascii
: result: src_emacs-lisp[:results replace]{42} {{{results(=42=)}}}
: exported as:
: `42'

* :results html under html backend

#+CALL: demo("html","html")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results html]{42}
: export backend: html
: result: src_emacs-lisp[:results html]{42} {{{results(@@html:42@@)}}}
: exported as:
: <p>
: 42</p>

* :results html under latex backend

#+CALL: demo("html","latex")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results html]{42}
: export backend: latex
: result: src_emacs-lisp[:results html]{42} {{{results(@@html:42@@)}}}
: exported as:

* :results latex under latex backend

#+CALL: demo("latex","latex")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results latex]{42}
: export backend: latex
: result: src_emacs-lisp[:results latex]{42} {{{results(@@latex:42@@)}}}
: exported as:
: 42

* :results replace :wrap ascii

#+CALL: demo("replace :wrap ascii","ascii")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results replace :wrap ascii]{42}
: export backend: ascii
: result: src_emacs-lisp[:results replace :wrap ascii]{42} 
{{{results(@@ascii:42@@)}}}
: exported as:
: 42

* :results raw

#+CALL: demo("raw")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results raw]{42}
: export backend: ascii
: result: src_emacs-lisp[:results raw]{42} 42
: exported as:
: 42

* :results drawer

Same as default.

#+CALL: demo("drawer")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results drawer]{42}
: export backend: ascii
: result: src_emacs-lisp[:results drawer]{42} {{{results(42)}}}
: exported as:
: 42

* :results org

Code is quoted like this: `42' under ascii backend.

#+CALL: demo("org")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results org]{42}
: export backend: ascii
: result: src_emacs-lisp[:results org]{42} {{{results(src_org{42})}}}
: exported as:
: `42'

* :results code

Code is quoted like this: `42' under ascii backend.

#+CALL: demo("code")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results code]{42}
: export backend: ascii
: result: src_emacs-lisp[:results code]{42} {{{results(src_emacs-lisp[]{42})}}}
: exported as:
: `42'

* :results list

Lists and tables should be avoided for inline-src-blocks, but for
completeness some are listed here.

#+CALL: demo("list")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results list]{42}
: export backend: ascii
: result: src_emacs-lisp[:results list]{42} {{{results(*Inline error:* 
`:results list')}}}
: exported as:
: *Inline error:* `:results list'

* :results table

#+CALL: demo("table")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results table]{42}
: export backend: ascii
: result: src_emacs-lisp[:results table]{42} {{{results(*Inline error:* 
`:results table')}}}
: exported as:
: *Inline error:* `:results table'

* :results replace, proper list as content

Proper lists become tables.

#+CALL: demo(contents="\'(42)")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results replace]{'(42) }
: export backend: ascii
: result: src_emacs-lisp[:results replace]{'(42) } {{{results(*Inline error:* 
list result)}}}
: exported as:
: *Inline error:* list result

* :results code, contents as elisp

#+CALL: demo("code",contents="(quote (+ 1 2))")

#+RESULTS:
: inline-src-block: src_emacs-lisp[:results code]{(quote (+ 1 2) )}
: export backend: ascii
: result: src_emacs-lisp[:results code]{(quote (+ 1 2) )} 
{{{results(src_emacs-lisp[]{(+ 1 2)
: })}}}
: exported as:
: src_emacs-lisp[]{(+ 1 2) }

Reply via email to