Archives | Categories

Orgmode Export Process

Table of Contents

<2014-03-26 Wed>

1. Overview

The org-mode export process consists of these steps:

  • run functions in org-export-before-processing-hook
  • expand include(#+INCLUDE: ...) keywords
  • expend macro({{{macro}}}) keywords
  • execute babel code blocks
  • run functions in org-export-before-parsing-hook
  • export with specified backend

You can use some of these steps to generate dynamic content during the export process.

2. Use macros to define text snippets

As the manaul page says, you can define text snippets with macro like this:

#+MACRO: use I use $1

then {{{use(Emacs)}}} will become 'I use Emacs' after export.

Yes, strictly, macro is not such dynamical, but only simple replacement(with arguments).

3. Use babel code blocks to generate content

You must have heard 'literal programming' if you are already an orgmode user: the awesome project Babel allows many different languages work together, we can export both the codes themselves and the output/return-value of them(yeah, by executing the codes). If you are still not very familiar with Babel, you can read the introduction right now, and I will give few simple samples here.

  • generate table by python code:

    #+BEGIN_SRC python :exports results :results table
      a = (1,2,"string \\vert string")
      b = (4,5,6)
     return (a,b)
    #+END_SRC
    

    will generate the table below:

    1 2 string | string
    4 5 6
  • generate raw output by elisp:
    • define a named code block

      #+name: test-0
      #+BEGIN_SRC elisp :exports none
        (princ "OUTPUT *STRING* will be captured")
      #+END_SRC
      
    • call the named code block test-0, capture the output:

      #+CALL: test-0[:results output]() :results raw
      

      the output will be considered as raw org source:

      OUTPUT STRING will be captured

4. Define named code blocks and macro in a separate file

The include keywords are expanded before macros expansion and babel code blocks execution, so you can write all frequently used macros and code blocks(with a name) in a separate org file, then include it in other org files, here is an example.

5. Use dynamic block to generate content

Babel code blocks and macros can satisfy our requirements of dynamic content generation in almost all situations, but, today I encounter an exceptional one:

I want to generate include instruction dynamically, because the path of the included file is calculated dynamically based on the path of current org file.

We can't use babel code blocks because these blocks are expanded after the expansion of the include keywords, neither can we use the macro because both of the expansion order and that macro expansion is only simple replacement.

What should I do? Fortunately we have anthor weapon: Dynamic Blocks. So I define a dynamic block to generate the include instruction dynamically:

(defun org-dblock-write:inc-file (params)
  (let ((file (plist-get params :file)))
    (insert (concat "#+INCLUDE: "
                    (get-path-dynamically)))))

and then add org-update-all-blocks to org-export-before-processing-hook :

(add-hook 'org-export-before-processing-hook
          (lambda (backend) (org-update-all-dblocks)))

Now, I can write:

#+BEGIN: inc-file :file "common.inc.org"
#+END:

in my org files, cheers!

6. More samples

I'm using orgmode to build this site, and the source can be found at https://github.com/KDr2/kdr2-on-web, you can find all the tricks I metioned above in this repository.

7. Discuss and Comment

Have few questions or feedback? Feel free to send me(killian.zhuo📧gmail.com) an email!

Copyright © KDr2, SOME RIGHTS RESERVED UNDER CC BY-NC 4.0.

Built with Emacs 28.2 (Org mode 9.5.5).

Last updated: 2022-01-28 Fri 13:42.