emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How is org-sbe supposed to work?


From: Daniele Nicolodi
Subject: Re: How is org-sbe supposed to work?
Date: Fri, 13 Nov 2020 22:56:48 +0100
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Thunderbird/68.12.1

On 13/11/2020 15:39, Daniele Nicolodi wrote:
> How are variables passed to the code block supposed to be handled? The
> macro docstring does not mention anything particular, thus I would
> imagine they are handled just like in any other lisp code. However, this
> does not seem to be the case.

After some more testing and starring at the code some more, it seems
that the odd behavior comes from the attempt of org-sbe to be clever and
do not require to use the N flag in the org table formula definition to
parse numbers as such, maybe.

Anyway, I came up with an alternative macro that does what I would
expect org-sbe to do, acting as a transparent interface to execute org
code blocks, without surprises:

(defun org-sbx1 (name header args)
  (let* ((args (mapconcat
                (lambda (x)
                  (format "%s=%S" (symbol-name (car x)) (cadr x)))
                args ", "))
         (ctx (list 'babel-call (list :call name
                                      :name name
                                      :inside-header header
                                      :arguments args
                                      :end-header ":results silent")))
         (info (org-babel-lob-get-info ctx)))
    (when info (org-babel-execute-src-block nil info))))

(defmacro org-sbx (name &rest args)
  (let* ((header (if (stringp (car args)) (car args) nil))
         (args (if (stringp (car args)) (cdr args) args)))
    (unless (stringp name)
      (setq name (symbol-name name)))
    (let ((result (org-sbx1 name header args)))
      (org-trim (if (stringp result) result (format "%S" result))))))

which I find significantly simpler than the implementation of org-sbe.
It works emulating what a #+call: directive does constructing by hand
the parsed version returned by org-element-parse. Demo:

#+name: sum
#+begin_src elisp :var x='(2 3)
  (apply '+ x)
#+end_src

#+name: concat
#+begin_src elisp :var x='()
  (apply 'concat x)
#+end_src

| 1 | 2 | 3 | 4 | 5 |    15 |    15 |
| a | b | c | d | e | abcde | abcde |
#+TBLFM: @1$6='(org-sbx sum (x '($1..$5)));N
#+TBLFM: @1$7='(apply '+ '($1..$5));N
#+TBLFM: @2$6='(org-sbx concat (x '($1..$5)))
#+TBLFM: @2$7='(apply 'concat '($1..$5))


The only problem I have with it is that the point jumps around during
evaluation and that while the macro is evaluated the formula definition
line is duplicated. I haven't yet investigated why (however the same
happens with org-sbe).

It may be that it is not too difficult to avoid having to convert the
arguments to a string representation and back, but this would require
digging a bit deeper into ob-core.el.

Cheers,
Dan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]