Create a template file, template.el, with these contents (this is the backquoted form of what you show above):
`(("default" . ((user-emacs-directory . "~/emacs-configs/my-config") (env . (("HOME" . ,(concat (getenv "APPDATA") "\\AG-Emacs")))))))
You can add org-babel-execute-buffer to org-babel-pre-tangle-hook to make sure that the pre-processing is done before the tangling. The backquote quotes the form just like ', except that it allows partial evaluation using the , mechanism (see Backquote in the Emacs Lisp Ref manual).
Assuming you have an environmental definition for APPDATA, if you cut-and-paste this form into your scratch buffer and evaluate it with C-j at the end of form, you will get your second form above (it may look different but it is actually the same list - the Lisp printer prefers to write list structure instead of dotted-pair structure whenever possible):
(("default" (user-emacs-directory . "~/emacs-configs/my-config") (env ("HOME" . "C:\\Users\\<username>\\AppData\\Roaming\\AG-Emacs"))))
You can do the pre-processing manually as above, or by using a script:
emacs --batch --load foo.el\ --eval '(ndk/pre-process "template.el")'
where foo.el looks like this:
;(setenv "APPDATA" "C:\\Users\\<username>\\AppData\\Roaming") (defun ndk/pre-process (file) (with-current-buffer (find-file-noselect file) (print (eval (read (current-buffer))))))
I tested with the setenv uncommented, since I did not have an environmental definition for APPDATA, but presumably you do, so you can leave the setenv commented out.
I didn't bother to write the output to a file in the script, since I can use redirection:
emacs --batch --load foo.el \ --eval '(ndk/pre-process "template.el")' > .emacs-profiles.el
But I don't know how to do this by using org-babel-tangle (and actually I don't think it's possible, at least not straightforwardly, but that may be a failure of imagination on my part).
EDIT:The following is close but fails because the elisp implementation of Org Babel has the bad habit of leaving out double quotes around strings:
* Code First, evaluate this code block to produce the expanded template in another code block - then `C-c C-v C-t' to tangle into `output.el': #+name: template #+begin_src elisp :results drawer :wrap src elisp `(("default" . ((user-emacs-directory . "~/emacs-configs/my-config") (env . (("HOME" . ,(concat (getenv "APPDATA") "\\AG-Emacs"))))))) #+end_src * Results :PROPERTIES: :header-args:elisp: :tangle output.el :END: #+RESULTS: template #+begin_src elisp ((default (user-emacs-directory . ~/emacs-configs/my-config) (env (HOME . C:\Users\<username>\AppData\Roaming\AG-Emacs)))) #+end_src
The output is:
((default (user-emacs-directory . ~/emacs-configs/my-config) (env (HOME . C:\Users\<username>\AppData\Roaming\AG-Emacs))))
Close, but no cigar...
EDIT 2: OK, this is ugly but it works:
#+name: template #+begin_src elisp :results output :wrap src elisp (print `(("default" . ((user-emacs-directory . "~/emacs-configs/my-config") (env . (("HOME" . ,(concat (getenv "APPDATA") "\\AG-Emacs")))))))) #+end_src
EDIT 3: Here's a function that you can add to org-babel-pre-tangle-hook. That way, the pre-processing will happen before tangling:
#+begin_src elisp (defun ndk/pre-tangle () "Execute the \"template\" src block before tangling." (save-excursion (org-babel-goto-named-src-block "template") (org-babel-execute-src-block))) #+end_src
It executes just the template block which fills out the result with the pre-processed code block in the Results section. The property in the section then tangles the result src block to the output.
2 + 3standing on its own; you can replace it by5but what good does that do? It will have no effect on anything. Is this the complete code block?.emacs-profiles.elconfig is specific to my current windows PC - since it mentionsC:\\Users\\<username>in the file path. So I cannot directly use the same.emcas-profiles.elconfig in another system as is. That's the reason I'm looking for this approach.. I'll add this point in the question