10

Including other .org files is quite easy. For example, for configuration,

#+setupfile: /path/to/config.org

or

#INCLUDE: /path/to/config.org

Those lines need to be in the .org file in order to be processed.

How could one have a given #+setupfile and #+include file available programmatically at export time, without having to insert them in the file?

Practical use case: we need to batch process several hundreds org-mode files from a read-only repository. Those files do not have any #+setupfile and #+include file. For example, we need to make available a few #+MACRO lines (see below).

For each org-mode file, I could read it in a buffer, inject the needed #+setupfile and #+include, export the file, and go to the next.

Is there a simpler way, like for example setting #+setupfile or #+include as variables, so that they are automatically available at export time?

Perhaps there is a way to add something to .dir-locals.el?

We even though of using some elisp within org-load-hook or org-mode-hook, but I could not find a way to pass content that needs to be evaluated as active Org-mode.

Just to give an idea, this is a much simplified #+SETUPFILE:

#+OPTIONS: H:1 num:nil author:nil creator:nil timestamp:nil email:nil toc:t \n:nil @:t     ::t |:t ^:t -:t f:t *:t TeX:t LaTeX:nil skip:nil d:t tags:not-in-toc


#+MACRO: fleuron @@latex:\fleuron@@ @@html:<center>* * *</center>@@
#+MACRO: newline @@latex:\\@@ @@html:<br>@@ @@ascii:|@@

#+LATEX_CLASS: book
#+LATEX_CLASS_OPTIONS: [a4paper,twoside,onecolumn]
#+LATEX_HEADER: \bibliographystyle{plain}
#+LATEX_HEADER: \bibliography{bibliography}
gsl
  • 1,742
  • 17
  • 34
  • 2
    What about `org-publish-project-alist` - maybe you could bind it repeatedly to different, dynamically constructed projects, or just create one large list of projects? – wvxvw Jan 16 '15 at 13:16
  • Thank you, I have added our current #+SETUPFILE just for more clarity. You can see we need to define macros as well, I am not sure how to do that with `org-publish-project-alist` properties. – gsl Jan 16 '15 at 13:22
  • 2
    As I write below, macros are expanded before `ox` starts parsing the file. See the comment at the heading `;;; Core functions` in `ox.el`. – rasmus Jan 16 '15 at 18:16
  • 2
    I was thinking more along the line of instead of including the file with macros in every file you export: use a project with the file with settings and include other files in it. I'll post example code soon. – wvxvw Jan 16 '15 at 18:35
  • Related question about support for `:setupfile` in `org-publish-project-alist` (see comments): http://emacs.stackexchange.com/questions/16623 – Christoph Sep 30 '15 at 13:41

2 Answers2

4

Here's some code to work from. The key is use org-export-before-processing-hook.

(defcustom rasmus/setup-file '("/tmp/setup.org")
  "list of string with setup file or functions.

Functions must take care of keyword themselves and must return
strings.")

(defcustom rasmus/setup-file-keyword "#+INCLUDE: "
  "Keyword used by `rasmus/org-export-setup-files'")

(defun rasmus/org-export-setup-files (backend)
  "Include setup-files automatically.  

See also `rasmus/setup-file' and `rasmus/setup-file-keyword'"
  ;; TODO: Resolve local files.
  ;; TODO: Better control over where contents is inserted.
  (save-excursion
(goto-char (point-max))
(insert "\n"
 (mapconcat
  (lambda (elm)
    (cond ((stringp elm)
       (concat rasmus/setup-file-keyword elm))
      (functionp elm) (funcall elm)
      (t (error "`rasmus/setup-file' should contain only strings and functions!"))))
  rasmus/setup-file
  "\n"))))

(add-hook 'org-export-before-processing-hook
      'rasmus/org-export-setup-files)

And a test:

(progn
  (require 'ox-org)
  (find-file "/tmp/setup")
  (insert "this is setup!")
  (save-buffer)
  (kill-buffer)
  (with-temp-buffer
(insert "* test\n")
(org-org-export-as-org))

Output:

# Created 2015-01-16 Fri 16:37
#+TITLE: 
* test

This is the setup file

# Emacs 24.4.1 (Org mode 8.3beta)
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
rasmus
  • 2,682
  • 13
  • 20
  • I am guessing from the answer that you do not think it is possible to do it without much coding (and I can't believe how fast you were able to code all this). I already upvoted the answer. Let me wait a few hours, and I will accept it as solving my question. Thank you so much for all the code. – gsl Jan 16 '15 at 15:55
  • 2
    Did you read the code? You can make it very compact by hardcoding everything. But I'd rather be verbose and allow for some limited flexibility (the posted code is not very flexible, actually). – rasmus Jan 16 '15 at 16:04
  • Yes, I read it and tested it. It is very helpful. I learned a lot, too. It is not that I am against coding, it was just a curiosity, since org-mode has so many hidden aspects. In the question I was wondering if there were some org-mode built-in variables (I guess list?) that would help take care of my use-case without resorting to much coding. But your code does fulfil the question. Thank you very much for it. – gsl Jan 16 '15 at 16:37
  • 1
    I haven't studied this much so take this with a grain of salt. INCLUDEd files are never collected. They are just expanded in the file. See `org-export-expand-include-keyword` which is called from `org-export-as` before the file is parsed. For some backends, it is possible to insert e.g. preambles ex post, e.g. `ox-html`, or `org-latex-classes` say, but that won't get you macros. Some variables can be set via `org-publish-project-alist`, e.g. `#+OPTION`s, but again macros are expanded earlier than that. – rasmus Jan 16 '15 at 18:08
  • Thank you for the helpful clarification. `MACRO`s are indeed essential. – gsl Jan 16 '15 at 18:12
  • 1
    I updated. I can never get used to stackexchange interpreting RET as submit for these things. – rasmus Jan 16 '15 at 18:13
  • Thanks for this, it has helped answer some questions I didn't know I had. – hraban May 16 '21 at 16:44
2

Here's the basic idea:

(defun export-files-with-template (template sources)
  (cl-loop for file in (file-expand-wildcards sources)
           do (with-temp-buffer
                (insert-file template)
                (insert (format "#+include: %s\n" file))
                (org-mode)
                (let ((exported (org-export-as 'html))
                      (save-silently-p t))
                  (with-temp-file
                      (format "%s.html" (file-name-sans-extension file))
                    (insert exported))))))

(export-files-with-template "~/org/setupfile.org" "~/org/example/*.org")

The ~/org/setupfile.org is the file that contains macro and export setting definitions, ~/org/example/*.org are the files that need to be exported. You could, of course add more export backends / extend this to projects / specify output directory etc.; this is just the basic idea.

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
wvxvw
  • 11,222
  • 2
  • 30
  • 55
  • Thank you, nice idea. Let me study your code, I will try to extend it with what we need. Thank you! – gsl Jan 16 '15 at 19:45