5

I want to create an org file with all my beamer lectures notes for one course.

With the example below I can generate my slides for a specific lecture with subtree export by positioning point within the drawer and pressing

C-c C-e C-s l P

(I have put common packages, etc., in the slides-preamble.tex file.)

* Lecture 1
  :PROPERTIES:
  :EXPORT_LaTeX_CLASS: beamer
  :EXPORT_LaTeX_CLASS_OPTIONS: [presentation]
  :EXPORT_BEAMER_THEME: default
  :EXPORT_FILE_NAME: L01-intro-slides.pdf
  :EXPORT_LATEX_HEADER: \input{slides-preamble.tex}
  :END:
** Lecture 1, Slide 1
   - Items
** Lecture 1, Slide 2
   - Items
* Lecture 2
  :PROPERTIES:
  :EXPORT_LaTeX_CLASS: beamer
  :EXPORT_LaTeX_CLASS_OPTIONS: [presentation]
  :EXPORT_BEAMER_THEME: default
  :EXPORT_FILE_NAME: C02-fundamentals.pdf
  :EXPORT_LATEX_HEADER: \input{slides-preamble.tex}
  :END:
** Lecture 2, Slide 1
   - Items

However, I would also like to be able to generate a handout set of my slides. I could change some of the properties to

  :EXPORT_LaTeX_CLASS_OPTIONS: [handout]
  :EXPORT_FILE_NAME: L01-intro-handouts.pdf
  :EXPORT_LATEX_HEADER: \input{handouts-preamble.tex}

and re-export (handouts-preamble.tex would containt, e.g., a \pgfpagesuselayout command, etc.). However I would like a more streamlined solution. Can anyone help me? I have searched and found quite a few Q&A that relate to this, but none that describes how to export a subtree to different files with different attributes.

Emacs 24.5.2, Org mode 9.1.

EDIT:

After debugging org-beamer-export-to-pdf and friends I'm thinking along the lines of writing two functions that would call said function with different ext-plists. However, I'm not sure of the format of ext-plist. Can anyone share an example?

1 Answer 1

2

After edebug-ing through org-export-to-file and peeking at related posts, including Export to multiple files according to tags, I have come up with the solution below. It keeps the necessary decorations in the org file at a minimum and uses some elisp code to do the presentation/handout switch. Note the caveat about global latex class options at the end.

org file content

#+LaTeX_CLASS: beamer
#+BEAMER_THEME: default
#+AUTHOR:    Niclas Börlin
#+LATEX_HEADER: \input{preamble.tex}
#+OPTIONS:   email:t num:t toc:nil \n:nil ::t |:t ^:t -:t f:t *:t <:t

* L01 - Introduction                                          :L01_intro:cur:
  :PROPERTIES:
  :EXPORT_DATE: 2017-10-31 Tue
  :END:
** Lecture 1, Slide 1
   - Items
** Lecture 1, Slide 2
   - Items
* L02 - Fundamentals                                       :L02_fundamentals:
  :PROPERTIES:
  :EXPORT_DATE: Fri 2017-11-03
  :END:
** Lecture 2, Slide 1
   - Items

Notes:

  • The header contains stuff common for all lectures.
  • It does not contain any LATEX_CLASS_OPTIONS. The handout will be handled programatically (see .emacs below).
  • It contains one line that includes preamble.tex.
  • Each lecture on its own top level. Slides within that lecture in sub-levels.
  • Lecture-specific properties, e.g. the lecture date, in a property drawer.
  • One unique tag per lecture. The tag also acts as a filename stub.
  • One :cur: tag that denotes my currently active lecture (to enable keyboards shortcuts).

preamble.tex content

\usepackage{lmodern}
\usepackage{tikz}
\usepackage{pgfplots}
\mode<handout>{
  \usepackage{pgfpages}
  \pgfpagesuselayout{4 on 1}[a4paper,border shrink=5mm,landscape]
}

Includes packages and settings common to all slides and lectures. The most important part is the conditional \mode<handout> snippet (see e.g. https://tex.stackexchange.com/questions/266116/trying-to-hide-blocks-of-text-in-beamer/) that sets up the handout format.

If you prefer, you could of course include the lines in preamble.tex as #+LaTeX_CLASS_OPTIONS: lines in your org file instead.

.emacs content

(defun export-slides-or-handouts (tagname handouts)
  "Export org subtree with tag tagname as beamer slides or handouts. If handout
is non-nil, exports to a file named tagname-handouts.tex and uses \"[handout]\"
as the class option. Otherwise, export to a file named tagname-slides.tex with
empty class option. Any underscore in tagname is replaced by a dash in the file
name."
  (save-excursion
    (beginning-of-buffer)
    ; Search for tagname
    (search-forward (concat ":" tagname ":"))
    (let ((org-export-select-tags (list tagname))
          (async nil)
          (subtreep t)
          (visible-only nil)
          (body-only nil)
          ; Use [handout] option if exporting handouts, otherwise empty.
          (ext-plist (if handouts '(:latex-class-options "[handout]")
                       '()))
          ; Export name is tagname (with underscores replaced by dashes)
          ; followed
          (export-name (concat (subst-char-in-string ?_ ?- tagname)
                               (if handouts "-handouts" "-slides")
                               ".tex")))
      (org-export-to-file 'beamer export-name async subtreep
          visible-only body-only ext-plist
          (lambda (file) (org-latex-compile file))))
    )
  )

(defun get-current-lecture-tag()
  "Return the first tag that appears together with the first :cur: tag in the file."
  (save-excursion
    (beginning-of-buffer)
    ; Search for first :cur: tag.
    (if (search-forward ":cur:" nil t)
        ; Return first tag in list, excluding :cur:
        (nth 0 (remove "cur" (org-get-tags)))
      (error (message "No :cur: tag found.")))))

(defun export-current-slides()
  "Export the subtree with the :cur: tag as beamer slides."
  (interactive)
  (let ((tag (get-current-lecture-tag)))
    (if tag
        (progn (message "Exporting %s slides" tag)
               (export-slides-or-handouts tag nil))
      (error (message "No tag on :cur: lecture")))))

(defun export-current-handouts()
  "Export the subtree with the :cur: tag as beamer handouts."
  (interactive)
  (let ((tag (get-current-lecture-tag)))
    (if tag
        (progn (message "Exporting %s handouts" tag)
               (export-slides-or-handouts tag t))
      (error (message "No tag on :cur: lecture")))))

(defun set-my-beamer-export-keys()
  (interactive)
  (local-set-key (kbd "<f12>") 'export-current-slides)
  (local-set-key (kbd "<S-f12>") 'export-current-handouts))

Notes

  • The function export-slides-or-handouts does a subtree export for a specific tag.
  • If handouts are requested, '(:latex-class-options "[handout]") is used for the ext-plist argument in the call to org-export-to-file. Otherwise, the property list is empty, i.e., no LaTeX class options. Without options, the default is to generate slides.
  • The used file name is either tagname-slides.tex or tagname-handouts.tex. (For aesthetic reasons, the code also replaces underscores with hyphens in tagname.)

The export-slides-or-handouts functions solves everything I need programmaticaly (see, e.g., EDIT2 of Export to multiple files according to tags). The other functions allow me easy access via function keys.

Usage:

  1. Start up emacs, open your-lecture-notes.org.
  2. Put necessary stuff in header.
  3. Do M-x set-my-beamer-export-keys to set up keys.
  4. Add a lecture with a title, give it a tag, add :cur: tag.
  5. Add slides, items, etc.
  6. Press F12 to export the current lecture notes as slide.
  7. Press S-F12 to export them as handouts.
  8. To shift focus to another lecture, move the :cur: tag.

Caveat

While the above solution is really nice to work with, there is room for improvement. For instance, as presented, my solution does not work with other beamer class options, e.g. 12pt, as the file-local options override the programmatical ones in ext-plist. (See, e.g., function comment for org-export-get-environment. A workaround is to modify export-slides-or-handouts to supply "[12pt,handout]" for handouts and "[12pt]" for slides. (Or supply the options as a parameter.)

Your Answer

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

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