The following elisp code defines a new dynamic block type babel
.
Babel dblocks resolve source code block references in the values of block heading properties.
The syntax is:
#+begin babel :dblock ACTUAL-TYPE :PROP1 VAL1 :PROP2 VAL2 ...
...
#+end
This babel block resolves references in the values VAL1, VAL2, ...
and delegates the remaining work to the following dynamic block. Thereby the source block references in VAL1, VAL2, ... are already resolved.
#+begin ACTUAL-TYPE :PROP1 VAL1 :PROP2 VAL2 ...
...
#+end
If the elisp snippet proves useful for you install it in your init file.
(defun plist-remove (plist &rest props)
"Return a copy of PLIST without property PROP."
(setq plist (cl-copy-list plist))
(dolist (prop props)
(let ((place (plist-member plist prop)))
(if (cddr place)
(progn
(setcar place (cl-caddr place))
(setcdr place (cl-cdddr place)))
(let ((n (length plist)))
(if (= n 2)
(setq plist nil)
(setf (nthcdr (- n 2) plist) nil))))))
plist)
(defun t-org-resolve-refs (expr)
"Resolve references to source blocks in EXPR."
(if (memq expr '(t nil))
expr
(cdr (org-babel-ref-parse (format "_=%s" expr)))))
(defun org-dblock-write:babel (params)
"Add support for babel dblocks resolving refs in PARAMS.
#+begin babel :dblock ACTUAL-TYPE :PROP1 VAL1 :PROP2 VAL2 ...
...
#+end
babel blocks resolve references in the values VAL1, VAL2, ...
and delegate the remaining work to the dynamic block
#+begin ACTUAL-TYPE :PROP1 VAL1 :PROP2 VAL2 ...
...
#+end
"
(let* ((dblock (plist-get params :dblock))
(dblock-name (symbol-name dblock))
(content (plist-get params :content))
(params-rest params)
(fun-name (concat "org-dblock-write:" dblock-name))
(fun (intern-soft fun-name)))
(cl-assert dblock nil "\"#+begin babel\" requires a \":dblock\" argument (see doc for `org-dblock-write:babel')")
(cl-assert fun nil "Dblocks of type \"%s\" do not have a write function `%s'" dblock-name fun-name)
(setq params-rest (plist-remove params-rest :name :dblock :content))
(cl-loop for pair on params-rest by #'cddr do
(setcar (cdr pair) (t-org-resolve-refs (cadr pair))))
(plist-put params-rest :name dblock)
(funcall fun params-rest)))
Tested with:
emacs-version
25.1.50
org-version
9.1.6
and the following clocktable block:
* Some Header
CLOCK: [2018-02-09 Fri 8:00]--[2018-02-09 Fri 16:00]
#+NAME: commit_date
#+BEGIN_SRC emacs-lisp :exports none :tangle no :dir ~/tmp/elgrep
(shell-command-to-string "git log -1 --format=%cd --date=format:\"<%Y-%m-%d %a %H:%M>\"")
#+END_SRC
#+RESULTS: commit_date
: <2018-02-04 Sun 03:25>
#+BEGIN: babel :dblock clocktable :maxlevel 3 :tstart commit_date :narrow 88 :compact nil
#+END:
Note that the header arguments of a dynamic babel block must form a valid alist. That is the reason why I added a nil
at the end.
call_commit_date()
is not evaluated.org-clock-get-table-data
just gets a list(call_commit_date nil)
as(plist-get params :tstart)
and not a string as you expect. It is not the same as for the:var
header arguments of source code blocks.