3

Here is an org document

#+title: my document
#+options: num:nil

* first section
** first subsection
* second section

My problem is that I want the option #+option: num:nil to only be applied when I export to html. When I export to other formats, I do not want this option applied. Is this possible?

4
  • Doess this help?
    – NickD
    Mar 22, 2021 at 0:48
  • @NickD Rather than do something fancy with multiple files and have to adjust the file for each export, I'd rather just comment/uncomment the option with each export. To me, a solution would be something that works for every export without my intervention. I'm kind of surprised there is a syntax like #+option_html for situations like this! Mar 22, 2021 at 1:53
  • Isn't that what this answer is supposed to do? (BTW, I have not tested it - I'm taking the author's assurance that it worked for him at face value). Granted, it's not as simple as having explicit #+OPTION_HTML syntax, but the latter is a moving target for Org-mode: every time somebody adds an exporter, the syntax of Org mode would have to change.
    – NickD
    Mar 22, 2021 at 2:18
  • please accept the given answer if it solves your problem :)
    – xeruf
    Jan 5, 2022 at 20:54

1 Answer 1

3

Macros

You can evaluate arbitrary Lisp code using a macro:

#+MACRO: macroname (eval <lisp code...>)

When the macro is expanded, the code is executed.

Using the Macro

So we can do something like this:

#+MACRO: options (eval (if (org-export-derived-backend-p org-export-current-backend 'html) "#+OPTIONS: num:nil"))

{{{options}}}

#+title: my document

* first section
** first subsection
* second section

org-export-current-backend is a dynamically scoped variable that is set by the exporter before it touches the document. Now when this document is exported, the macro is defined and it is then expanded (through the {{{options}}} macro call). The Lisp expression is evaluated and if the current backend is (or is derived from) the HTML backend, then the #+OPTIONS: num:nil string is the result of the evaluation - and the expansion of the macro. Since macros are expanded as the first step in the export process, the rest of the export proceeds as if the options string was already included in the file.

Including lisp functions

Here is an elaboration of the idea above to work around the fact (AFAIK) that the macro definition needs to be in a single line. Define a Lisp function to do what you want (which may be arbitrarily complicated) and then eval the call to the function in the macro definition:

#+MACRO: options (eval (ndk/options org-export-current-backend))
{{{options}}}

* foo
This is foo

** foo.2
This is foo.2
* bar
This is bar
* baz
This is baz

* Code                                                                  :noexport:

#+begin_src elisp
  (defun ndk/options (be)
     "Different options for different backends. Caveat: this function needs to be
      defined, before the file is exported. And if e.g. an option changes, it needs to
      be defined again (just run the code block with `C-c C-c')."
     (cond
      ((org-export-derived-backend-p be 'latex) "#+OPTIONS: latex:t num:t toc:nil")
      ((org-export-derived-backend-p be 'html) "#+OPTIONS: html:t num:nil toc:t")))
#+end_src

That works OK interactively, but not in batch mode: You would have to store the definition of the function in some file and then use emacs --batch -l file.el .... to load it.

But that can be done by giving the code block a name and using the org-sbe function to do the evaluation of the code block. We can then incorporate that into the definition of the macro, so that when it is expanded, it first evaluates the code block and then it calls the function to produce the options:

#+MACRO: options (eval (progn (org-sbe "ndk/options") (ndk/options org-export-current-backend)))

{{{options}}}

... as before ...

* Code                                                                  :noexport:

#+name: ndk/options
#+begin_src elisp
    ... as before ...
#+end_src

You can now go wild in the function - nothing else needs to be touched.

Conclusion

With multiple #+OPTIONS lines, you can set defaults for every backend and use the macro to override only backend-dependent options (later #+OPTIONS lines override earlier ones):

#+MACRO: ....
#+OPTIONS: ... backend-independent options go here ...
{{{options}}}

...

The main idea was presented by Juan Manuel Macías on the Org mode mailing list - see this post and its enclosing thread.

Your Answer

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

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