Org Teach Export Macros
After using James Howell's Org Teach for a number of semesters, there was one
thing that was bothering me with the reproduction of images (and code) between
slides and handouts. Chiefly, images may have different scaling requirements
depending on whether the target output is the slide deck or the handout.
Initially, I simply built each document, manually replacing the appropriate
#+ATTR_LATEX lines to suit. Of course, this cannot stand.
Org mode has excellent export options, particularly for PDF output via LaTeX. Combined with some macros and standard files, and Org mode provides some significant functionality for creating and publishing documents in multiple formats. To that end, I have used Org Teach since I started teaching, and I have thoroughly enjoyed the experience. More importantly, my students have overwhelmingly preferred it, one student asking me to tell the other lecturers to similarly structure their content.
Including images into the final output is as easy as linking to the image file
using the standard Org linking syntax, e.g., [[URL][Description]].
Furthermore, we can provide customized LaTeX options to these links using
#+ATTR_LATEX lines immediately preceding these image links. Similarly Org
supports #+ATTR_BEAMER which differentiates options only available when
exporting Beamer slides.
Unfortunately, not all export elements go through the same code. For example,
using #+ATTR_BEAMER with images or code fragments does not in fact modify the
behavior since it is not merged into the dictionary of options by the different
translation functions within Org mode. Thus, when an image is particularly
tall for a slide, perhaps we want to cap its height with :height
0.7\textheight. However, for the handout, this would mean the image is now
70% of the page. Thus, we need a mechanism to set the height for both export
targets without going crazy.
To be clear, a better solution is to patch these functions within Org such that it merges
#+ATTR_BEAMERand#+ATTR_LATEXin a sensible way depending on the backend. In other words, when exporting to a regular LaTeX PDF, e.g., handouts, the exporter ignores#+ATTR_BEAMERlines. However, when exporting to Beamer, the exporter merges and replaces any values in the original#+ATTR_LATEXwith the values found in#+ATTR_BEAMER. Unfortunately, this is beyond my time capacity.
Instead of leveraging a proper solution, I wrote a set of (quite simple) macros to accomplish 80% of the desired result (the remaining 20% to resolve is the unfortunate but necessary duplication of common values between the two macros' arguments).
That is, I have defined the following macros:
#+MACRO: opts-if-beamer (eval (if (eq org-export-current-backend 'beamer) (format "#+ATTR_LATEX: %s" $1) "#+ATTR_LATEX:")) #+MACRO: opts-if-latex (eval (if (eq org-export-current-backend 'latex) (format "#+ATTR_LATEX: %s" $1) "#+ATTR_LATEX:"))
They are used as shown in the following example:
{{{opts-if-beamer(:placment [H] :center t :alt "")}}} {{{opts-if-latex(:placment [H] :center t :alt "")}}} ./link/to/image.png
Both macros take an argument and format it into the output Org source
immediately before the export engine takes over (you know, because macro
expansion is a preprocessing step of translation). Considering first the
org-if-beamer macro, if the target backend is Beamer, its eval returns the
appropriate #+ATTR_LATEX line with the arguments included. Otherwise, if it is
not, then it simply inserts a blank #+ATTR_LATEX line. Dually so for the the
opts-if-latex macro.
The blank
#+ATTR_LATEXis necessary as the exporter merges all grouped#+ATTR_LATEXlines together. Thus, without this line, the output is likely to have a spurious blank line separating theATTRlines, yielding undesired outputs.
These macros look like a lot of text to add each time an image needs insertion,
and that is true. However, I have added a Yasnippet for Org files to alleviate
this specific suffering. Now, I simply type <ins-image>TAB and I get the above
macro lines.
As an added benefit, I have found that these macros work quite well for source listings as well. Sometimes, I would like to display lots of source lines (~20 lines). However, this many lines do not fit well onto a Beamer slide. Thus, the font needs down scaling for the specific listing. However, the scaling should remain for the handout. Without any changes, we can use the same macros to accomplish this.
{{{opts-if-beamer(:options fontsize=\tiny)}}} {{{opts-if-latex()}}} #+begin_src scheme (define (sum seq) (if (null? seq) 0 (+ (car seq) (sum (cdr seq))))) (display (sum '(5 6 1 8 3 7))) (display "\n") #+end_src
Moving forward, while I enjoy the ability to easily create two kinds of
documents: one for presenting and one for handouts, I am reflecting on the
delivery modality some. That is, I may be experimenting with this process
more. Furthermore, given the recent dumpster fire Canvas outage, I have put
some thought into posting the handouts through GitHub or GitLab pages.
Unfortunately, this would mean I need to support another export backend. So
far, this seems doable by switching to a cond instead, but would mean there is
now an ordering requirement between the macros, gross.