Built-in approach
The noweb approach is built in to Org-mode but I believe it is a bit clumsy for your purpose. Therewith you can substitute marked names in source blocks with their result values within a source block. Thereby, the names are themselves names of source blocks that are evaluated to get the results.
Applied to your example that could look like the following snippet. In that snippet the noweb reference <<argsubst1()>>
is replaced with abcde
.
#+NAME: argsubst
#+BEGIN_SRC emacs-lisp :var argument="default value"
argument
#+END_SRC
#+NAME: argsubst1
#+CALL: argsubst("abcde")
#+NAME: conf
#+BEGIN_SRC conf :tangle /tmp/mine.conf :noweb yes
setting1 1234
setting2 <<argsubst1()>>
#+END_SRC
Alternative approach with customized execution of org-blocks
(At first a warning: The code below looks longer than the code above. But it defines also an Elisp function that you can move to your init file if you like it. Furthermore it demonstrates the generation of two conf
files with different parametrization.)
An alternative is to use parametrized org source blocks. The org-babel-execute:org
function below carries out the parameter substitution at execution of the org source block.
After running the calls to the org source block you can export or tangle the generated conf
source blocks.
Org-mode
does not have org-babel-execute:org
by default. So we can define one which substitutes the values of variables in its contents:
#+BEGIN_SRC emacs-lisp :results none
(defun org-babel-execute:org (body params)
"Return BODY with variables from PARAMS replaced by their values."
(let* ((vars (cl-loop for par in params
if (eq (car par) :var)
collect (cons (symbol-name (cadr par)) (cddr par))))
(re (regexp-opt (mapcar #'car vars) 'words))
(pos 0))
(while (string-match re body pos)
(setq body (replace-match
(format "%s" (cdr (assoc-string (match-string 0 body) vars)))
nil nil
body)))
body))
#+END_SRC
#+NAME: myconfig
#+BEGIN_SRC org :var argument="abcde", configFile="mine.conf" :results raw :tangle no
,#+BEGIN_SRC conf :tangle /tmp/configFile
setting1 1234
setting2 argument
,#+END_SRC
#+END_SRC
#+RESULTS: myconfig
#+BEGIN_SRC conf :tangle /tmp/mine.conf
setting1 1234
setting2 abcde
#+END_SRC
#+CALL: myconfig(argument="fghijk", configFile="yours.conf")
#+RESULTS:
#+BEGIN_SRC conf :tangle /tmp/yours.conf
setting1 1234
setting2 fghijk
#+END_SRC
If you like this approach you can move the function org-babel-execute:org
into your init file. In that case you do not need the Elisp source block anymore in your Org file.
If the package authors of Org invent by accident some org-babel-execute:org
function that does not what you want you can just derive your own mode from org-mode
with define-derived-mode
, e.g., myorg-mode
and change the name of org-babel-execute:org
above appropriately, in the example: org-babel-execute:myorg
.
In that case you use a myorg
source block in place of the org
source block above.