To cut down on some repetitive boilerplate, I'm attempting to make my header arguments more "dynamic", but I have run into what I believe is a "scope" issue, that I cannot yet get around.

I would like to move the :prologue arg from the cfg_* source code blocks into the :header-args: of the parent section. Here's an MVE for the context:

* CFG Generation
#+NAME: Platforms
| platform   | arch  | subarch | modelname             |
| ar300m     | ath79 | generic | glinet_gl-ar300m-lite |
| archerC7V5 | ath79 | generic | tplink_archer-c7-v5   |

#+NAME: cfg-mk-dev-header
#+BEGIN_SRC emacs-lisp :var dev="devsoc" platforms=Platforms :tangle no
(format "Long String generated from the above table\n")

** Devices
:header-args:  :noweb yes
:header-args+: :tangle (concat "cfg." (substring (org-element-property :name (org-element-context)) 3) ".gen")

*** ar300m - Device friendly name
#+NAME: cfg_ar300m
#+HEADER: :prologue (org-sbe cfg-mk-dev-header (dev '"ar300m"))
# ...

*** archerC7V5 - Friendly Name
#+NAME: cfg_archerC7V5
#+HEADER: :prologue (org-sbe cfg-mk-dev-header (dev '"archerC7V5"))

The problematic line is:

#+HEADER: :prologue (org-sbe cfg-mk-dev-header (dev '"ar300m"))

When I move this line into the :header-args:, and replace the static part '"ar300m" with (substring (org-element-property :name (org-element-context)) 3) like for :tangle, I then get

:prologue (org-sbe cfg-mk-dev-header (dev (substring (org-element-property :name (org-element-context)) 3)))

But when tangling the name-lookup fails, and I get the "default string" inserted in all config file.

Edit: Solved: I had the offset wrong-by-one (3 instead of 4). Many thanks to @NickD for helping with the initial issue of "lisp max nesting", and then pointing me to the "bug", which requires to wrap the result of the name lookup in (format "\"%s\"" ...)


1 Answer 1


For the Lisp nesting problem, make sure that your cfg-make-device-header block is NOT under the influence of those properties, otherwise when the block is evaluated to e.g. calculate the prologue of the other block, the headers apply to it as well, so you recurse infinitely.

And there is a quoting problem because... I don't know, I couldn't figure it out. It's probably a bug in org-sbe where it fails to protect its argument when it is a string, since the code block seems to return it without double quotes. But the following structure seems to work for me:

#+name: cfg-make-device-header
#+begin_src shell :var dev="foo"
echo $dev

* Devices
:header-args: :noweb yes
:header-args+: :prologue (org-sbe "cfg-make-device-header" (dev (format "\"%s\"" (substring (org-element-property :name (org-element-context)) 3))))
:header-args+: :tangle (concat "config." (substring (org-element-property :name (org-element-context)) 3) ".gen")

** Device frobuzz
   #+name: frobuzz
   #+begin_src sh
   echo foo

Note that the value of dev in the prologue has to be formatted with double quotes in order for this to work. But frankly, this seems way too fragile and debugging it is almost impossible: there are too many layers in the onion. I'd rethink the approach and probably replace the cfg-make-devices-header block with a lisp function, so as to avoid using org-sbe.

  • Many thanks for your answer! Yes, cfg-mk-dev-header was further down, but still in the device section scope, and thus created the infinite nesting. Oops, Duh... Thanks there for pointing me in the right direction. :) It helped me get further. but revealed a follow-up problem. I've updated the post. Sorry for slightly shifting the goalpost. Could you have a look again, please? Commented Aug 27, 2021 at 8:50
  • 1
    I tried putting the whole cfg-mk-dev-header (i've shortened some names from my original, so that more "meat" fits into the lines in this post without scrolling) verbatim into the :header-args: :prologue, but then i don't know, how to get the Platforms table. That table is much longer IRL, and the plan is to have all subsections of the (long) Devices chapter autogenerated from another table listing device features. I plan to use an :epilogue in similar fashion Commented Aug 27, 2021 at 8:55
  • 1
    Hi, thanks for your help. I believe, i found/fixed my problem. ... The offset of "ar300m" in "cfg_ar300m" is 4, not 3 ... "Duh" again on my end. I'll edit the OP a bit later Commented Aug 27, 2021 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.