org-export: Fix expansion of babel calls in included files
[org-mode.git] / contrib / lisp / org-e-beamer.el
blob94336d736be81868cdc26ae6cf60c441f5eeace6
1 ;;; org-e-beamer.el --- Beamer Back-End for Org Export Engine
3 ;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
5 ;; Author: Carsten Dominik <carsten.dominik AT gmail DOT com>
6 ;; Nicolas Goaziou <n.goaziou AT gmail DOT com>
7 ;; Keywords: org, wp, tex
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22 ;;; Commentary:
24 ;; This library implements both a Beamer back-end, derived from the
25 ;; LaTeX one and a minor mode easing structure edition of the
26 ;; document.
28 ;; Depending on the desired output format, three commands are provided
29 ;; for export: `org-e-beamer-export-as-latex' (temporary buffer),
30 ;; `org-e-beamer-export-to-latex' ("tex" file) and
31 ;; `org-e-beamer-export-to-pdf' ("pdf" file).
33 ;; On top of buffer keywords supported by `e-latex' back-end (see
34 ;; `org-e-latex-options-alist'), this back-end introduces the
35 ;; following keywords: "BEAMER_THEME", "BEAMER_COLOR_THEME",
36 ;; "BEAMER_FONT_THEME", "BEAMER_INNER_THEME" and "BEAMER_OUTER_THEME".
37 ;; All accept options in square brackets.
39 ;; Moreover, headlines now fall into three categories: sectioning
40 ;; elements, frames and blocks.
42 ;; - Like `e-latex' back-end sectioning elements are still set through
43 ;; `org-e-latex-classes' variable.
45 ;; - Headlines become frames when their level is equal to
46 ;; `org-e-beamer-frame-level' (or "H" value in the OPTIONS line).
47 ;; Though, if an headline in the current tree has a "BEAMER_env"
48 ;; (see below) property set to "frame", its level overrides the
49 ;; variable.
51 ;; - All frames' children become block environments. Special block
52 ;; types can be enforced by setting headline's "BEAMER_env" property
53 ;; to an appropriate value (see `org-e-beamer-environments-default'
54 ;; for supported value and `org-e-beamer-environments-extra' for
55 ;; adding more).
57 ;; - As a special case, if the "BEAMER_env" property is set to either
58 ;; "appendix", "note", "noteNH" or "againframe", the headline will
59 ;; become, respectively, an appendix, a note (within frame or
60 ;; between frame, depending on its level), a note with its title
61 ;; ignored or an againframe command. In the latter case,
62 ;; a "BEAMER_ref" property is mandatory in order to refer to the
63 ;; frame being resumed, and contents are ignored.
65 ;; Also, an headline with an "ignoreheading" value will have its
66 ;; contents only inserted in the output. This special value is
67 ;; useful to have data between frames, or to properly close
68 ;; a "column" environment.
70 ;; Along with "BEAMER_env", headlines also support "BEAMER_act" and
71 ;; "BEAMER_opt" properties. The former is translated as an
72 ;; overlay/action specification (or a default overlay specification
73 ;; when enclosed within square brackets) whereas the latter specifies
74 ;; options for the current frame ("fragile" option is added
75 ;; automatically, though).
77 ;; Every plain list has support for `:overlay' attribute (through
78 ;; ATTR_BEAMER affiliated keyword). Also, ordered (resp. description)
79 ;; lists make use of `:template' (resp. `:long-text') attribute.
81 ;; Eventually, an export snippet with a value enclosed within angular
82 ;; brackets put at the beginning of an element or object whose type is
83 ;; among `bold', `item', `link', `radio-target' and `target' will
84 ;; control its overlay specifications.
86 ;; On the minor mode side, `org-e-beamer-select-environment' (bound by
87 ;; default to "C-c C-b") and `org-e-beamer-insert-options-template'
88 ;; are the two entry points.
90 ;;; Code:
92 (require 'org-e-latex)
96 ;;; User-Configurable Variables
98 (defgroup org-export-e-beamer nil
99 "Options specific for using the beamer class in LaTeX export."
100 :tag "Org Beamer"
101 :group 'org-export
102 :version "24.2")
104 (defcustom org-e-beamer-frame-level 1
105 "The level at which headlines become frames.
107 Headlines at a lower level will be translated into a sectioning
108 structure. At a higher level, they will be translated into
109 blocks.
111 If an headline with a \"BEAMER_env\" property set to \"frame\" is
112 found within a tree, its level locally overrides this number.
114 This variable has no effect on headlines with the \"BEAMER_env\"
115 property set to either \"ignoreheading\", \"appendix\", or
116 \"note\", which will respectively, be invisible, become an
117 appendix or a note.
119 This integer is relative to the minimal level of an headline
120 within the parse tree, defined as 1."
121 :group 'org-export-e-beamer
122 :type 'integer)
124 (defcustom org-e-beamer-frame-default-options ""
125 "Default options string to use for frames.
126 For example, it could be set to \"allowframebreaks\"."
127 :group 'org-export-e-beamer
128 :type '(string :tag "[options]"))
130 (defcustom org-e-beamer-column-view-format
131 "%45ITEM %10BEAMER_env(Env) %10BEAMER_act(Act) %4BEAMER_col(Col) %8BEAMER_opt(Opt)"
132 "Column view format that should be used to fill the template."
133 :group 'org-export-e-beamer
134 :type '(choice
135 (const :tag "Do not insert Beamer column view format" nil)
136 (string :tag "Beamer column view format")))
138 (defcustom org-e-beamer-theme "default"
139 "Default theme used in Beamer presentations."
140 :group 'org-export-e-beamer
141 :type '(choice
142 (const :tag "Do not insert a Beamer theme" nil)
143 (string :tag "Beamer theme")))
145 (defcustom org-e-beamer-environments-extra nil
146 "Environments triggered by tags in Beamer export.
147 Each entry has 4 elements:
149 name Name of the environment
150 key Selection key for `org-e-beamer-select-environment'
151 open The opening template for the environment, with the following escapes
152 %a the action/overlay specification
153 %A the default action/overlay specification
154 %o the options argument of the template
155 %h the headline text
156 %H if there is headline text, that text in {} braces
157 %U if there is headline text, that text in [] brackets
158 close The closing string of the environment."
159 :group 'org-export-e-beamer
160 :type '(repeat
161 (list
162 (string :tag "Environment")
163 (string :tag "Selection key")
164 (string :tag "Begin")
165 (string :tag "End"))))
167 (defcustom org-e-beamer-outline-frame-title "Outline"
168 "Default title of a frame containing an outline."
169 :group 'org-export-e-beamer
170 :type '(string :tag "Outline frame title"))
172 (defcustom org-e-beamer-outline-frame-options ""
173 "Outline frame options appended after \\begin{frame}.
174 You might want to put e.g. \"allowframebreaks=0.9\" here."
175 :group 'org-export-e-beamer
176 :type '(string :tag "Outline frame options"))
180 ;;; Internal Variables
182 (defconst org-e-beamer-column-widths
183 "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0.0 :ETC"
184 "The column widths that should be installed as allowed property values.")
186 (defconst org-e-beamer-environments-special
187 '(("againframe" "F")
188 ("appendix" "x")
189 ("column" "c")
190 ("frame" "f")
191 ("ignoreheading" "i")
192 ("note" "n")
193 ("noteNH" "N"))
194 "Alist of environments treated in a special way by the back-end.
195 Keys are environment names, as strings, values are bindings used
196 in `org-e-beamer-select-environment'. Environments listed here,
197 along with their binding, are hard coded and cannot be modified
198 through `org-e-beamer-environments-extra' variable.")
200 (defconst org-e-beamer-environments-default
201 '(("block" "b" "\\begin{block}%a{%h}" "\\end{block}")
202 ("alertblock" "a" "\\begin{alertblock}%a{%h}" "\\end{alertblock}")
203 ("verse" "v" "\\begin{verse}%a %% %h" "\\end{verse}")
204 ("quotation" "q" "\\begin{quotation}%a %% %h" "\\end{quotation}")
205 ("quote" "Q" "\\begin{quote}%a %% %h" "\\end{quote}")
206 ("structureenv" "s" "\\begin{structureenv}%a %% %h" "\\end{structureenv}")
207 ("theorem" "t" "\\begin{theorem}%a%U" "\\end{theorem}")
208 ("definition" "d" "\\begin{definition}%a%U" "\\end{definition}")
209 ("example" "e" "\\begin{example}%a%U" "\\end{example}")
210 ("exampleblock" "E" "\\begin{exampleblock}%a{%h}" "\\end{exampleblock}")
211 ("proof" "p" "\\begin{proof}%a%U" "\\end{proof}")
212 ("beamercolorbox" "o" "\\begin{beamercolorbox}%o{%h}" "\\end{beamercolorbox}"))
213 "Environments triggered by properties in Beamer export.
214 These are the defaults - for user definitions, see
215 `org-e-beamer-environments-extra'.")
217 (defconst org-e-beamer-verbatim-elements
218 '(code example-block fixed-width inline-src-block src-block verbatim)
219 "List of element or object types producing verbatim text.
220 This is used internally to determine when a frame should have the
221 \"fragile\" option.")
225 ;;; Internal functions
227 (defun org-e-beamer--normalize-argument (argument type)
228 "Return ARGUMENT string with proper boundaries.
230 TYPE is a symbol among the following:
231 `action' Return ARGUMENT within angular brackets.
232 `defaction' Return ARGUMENT within both square and angular brackets.
233 `option' Return ARGUMENT within square brackets."
234 (if (not (string-match "\\S-" argument)) ""
235 (case type
236 (action (if (string-match "\\`<.*>\\'" argument) argument
237 (format "<%s>" argument)))
238 (defaction (cond
239 ((string-match "\\`\\[<.*>\\]\\'" argument) argument)
240 ((string-match "\\`<.*>\\'" argument)
241 (format "[%s]" argument))
242 ((string-match "\\`\\[\\(.*\\)\\]\\'" argument)
243 (format "[<%s>]" (match-string 1 argument)))
244 (t (format "[<%s>]" argument))))
245 (option (if (string-match "\\`\\[.*\\]\\'" argument) argument
246 (format "[%s]" argument)))
247 (otherwise argument))))
249 (defun org-e-beamer--element-has-overlay-p (element)
250 "Non-nil when ELEMENT has an overlay specified.
251 An element has an overlay specification when it starts with an
252 `e-beamer' export-snippet whose value is between angular
253 brackets. Return overlay specification, as a string, or nil."
254 (let ((first-object (car (org-element-contents element))))
255 (when (eq (org-element-type first-object) 'export-snippet)
256 (let ((value (org-element-property :value first-object)))
257 (and (string-match "\\`<.*>\\'" value) value)))))
261 ;;; Define Back-End
263 (org-export-define-derived-backend e-beamer e-latex
264 :export-block "BEAMER"
265 :sub-menu-entry
266 (?l (?B "As TEX buffer (Beamer)" org-e-beamer-export-as-latex)
267 (?b "As TEX file (Beamer)" org-e-beamer-export-to-latex)
268 (?P "As PDF file (Beamer)" org-e-beamer-export-to-pdf)
269 (?O "As PDF file and open (Beamer)"
270 (lambda (s v b)
271 (org-open-file (org-e-beamer-export-to-pdf s v b)))))
272 :options-alist
273 ((:beamer-theme "BEAMER_THEME" nil org-e-beamer-theme)
274 (:beamer-color-theme "BEAMER_COLOR_THEME" nil nil t)
275 (:beamer-font-theme "BEAMER_FONT_THEME" nil nil t)
276 (:beamer-inner-theme "BEAMER_INNER_THEME" nil nil t)
277 (:beamer-outer-theme "BEAMER_OUTER_THEME" nil nil t)
278 (:headline-levels nil "H" org-e-beamer-frame-level))
279 :translate-alist ((bold . org-e-beamer-bold)
280 (export-block . org-e-beamer-export-block)
281 (export-snippet . org-e-beamer-export-snippet)
282 (headline . org-e-beamer-headline)
283 (item . org-e-beamer-item)
284 (keyword . org-e-beamer-keyword)
285 (link . org-e-beamer-link)
286 (plain-list . org-e-beamer-plain-list)
287 (radio-target . org-e-beamer-radio-target)
288 (target . org-e-beamer-target)
289 (template . org-e-beamer-template)))
293 ;;; Transcode Functions
295 ;;;; Bold
297 (defun org-e-beamer-bold (bold contents info)
298 "Transcode BLOCK object into Beamer code.
299 CONTENTS is the text being bold. INFO is a plist used as
300 a communication channel."
301 (format "\\alert%s{%s}"
302 (or (org-e-beamer--element-has-overlay-p bold) "")
303 contents))
306 ;;;; Export Block
308 (defun org-e-beamer-export-block (export-block contents info)
309 "Transcode an EXPORT-BLOCK element into Beamer code.
310 CONTENTS is nil. INFO is a plist used as a communication
311 channel."
312 (when (member (org-element-property :type export-block) '("BEAMER" "LATEX"))
313 (org-remove-indentation (org-element-property :value export-block))))
316 ;;;; Export Snippet
318 (defun org-e-beamer-export-snippet (export-snippet contents info)
319 "Transcode an EXPORT-SNIPPET object into Beamer code.
320 CONTENTS is nil. INFO is a plist used as a communication
321 channel."
322 (let ((backend (org-export-snippet-backend export-snippet))
323 (value (org-element-property :value export-snippet)))
324 ;; Only "e-latex" and "e-beamer" snippets are retained.
325 (cond ((eq backend 'e-latex) value)
326 ;; Ignore "e-beamer" snippets specifying overlays.
327 ((and (eq backend 'e-beamer)
328 (or (org-export-get-previous-element export-snippet info)
329 (not (string-match "\\`<.*>\\'" value))))
330 value))))
333 ;;;; Headline
335 ;; The main function to translate an headline is
336 ;; `org-e-beamer-headline'.
338 ;; Depending on the level at which an headline is considered as
339 ;; a frame (given by `org-e-beamer--frame-level'), the headline is
340 ;; either a section (`org-e-beamer--format-section'), a frame
341 ;; (`org-e-beamer--format-frame') or a block
342 ;; (`org-e-beamer--format-block').
344 ;; `org-e-beamer-headline' also takes care of special environments
345 ;; like "ignoreheading", "note", "noteNH", "appendix" and
346 ;; "againframe".
348 (defun org-e-beamer--get-label (headline info)
349 "Return label for HEADLINE, as a string.
351 INFO is a plist used as a communication channel.
353 The value is either the label specified in \"BEAMER_opt\"
354 property, or a fallback value built from headline's number. This
355 function assumes HEADLINE will be treated as a frame."
356 (let ((opt (org-element-property :beamer-opt headline)))
357 (if (and (org-string-nw-p opt)
358 (string-match "\\(?:^\\|,\\)label=\\(.*?\\)\\(?:$\\|,\\)" opt))
359 (match-string 1 opt)
360 (format "sec-%s"
361 (mapconcat 'number-to-string
362 (org-export-get-headline-number headline info)
363 "-")))))
365 (defun org-e-beamer--frame-level (headline info)
366 "Return frame level in subtree containing HEADLINE.
367 INFO is a plist used as a communication channel."
369 ;; 1. Look for "frame" environment in parents, starting from the
370 ;; farthest.
371 (catch 'exit
372 (mapc (lambda (parent)
373 (when (equal (org-element-property :beamer-env parent) "frame")
374 (throw 'exit (org-export-get-relative-level parent info))))
375 (reverse (org-export-get-genealogy headline)))
376 nil)
377 ;; 2. Look for "frame" environment in HEADLINE.
378 (and (equal (org-element-property :beamer-env headline) "frame")
379 (org-export-get-relative-level headline info))
380 ;; 3. Look for "frame" environment in sub-tree.
381 (org-element-map
382 headline 'headline
383 (lambda (hl)
384 (when (equal (org-element-property :beamer-env hl) "frame")
385 (org-export-get-relative-level hl info)))
386 info 'first-match)
387 ;; 4. No "frame" environment in tree: use default value.
388 (plist-get info :headline-levels)))
390 (defun org-e-beamer--format-section (headline contents info)
391 "Format HEADLINE as a sectioning part.
392 CONTENTS holds the contents of the headline. INFO is a plist
393 used as a communication channel."
394 ;; Use `e-latex' back-end output, inserting overlay specifications
395 ;; if possible.
396 (let ((latex-headline
397 (funcall (cdr (assq 'headline org-e-latex-translate-alist))
398 headline contents info))
399 (mode-specs (org-element-property :beamer-act headline)))
400 (if (and mode-specs
401 (string-match "\\`\\\\\\(.*?\\)\\(?:\\*\\|\\[.*\\]\\)?{"
402 latex-headline))
403 (replace-match (concat (match-string 1 latex-headline)
404 (format "<%s>" mode-specs))
405 nil nil latex-headline 1)
406 latex-headline)))
408 (defun org-e-beamer--format-frame (headline contents info)
409 "Format HEADLINE as a frame.
410 CONTENTS holds the contents of the headline. INFO is a plist
411 used as a communication channel."
412 (let ((fragilep
413 ;; FRAGILEP is non-nil when HEADLINE contains an element
414 ;; among `org-e-beamer-verbatim-elements'.
415 (org-element-map headline org-e-beamer-verbatim-elements 'identity
416 info 'first-match)))
417 (concat "\\begin{frame}"
418 ;; Overlay specification, if any. When surrounded by
419 ;; square brackets, consider it as a default
420 ;; specification.
421 (let ((action (org-element-property :beamer-act headline)))
422 (cond
423 ((not action) "")
424 ((string-match "\\`\\[.*\\]\\'" action )
425 (org-e-beamer--normalize-argument action 'defaction))
426 (t (org-e-beamer--normalize-argument action 'action))))
427 ;; Options, if any.
428 (let* ((beamer-opt (org-element-property :beamer-opt headline))
429 (options
430 ;; Collect options from default value and headline's
431 ;; properties. Also add a label for links.
432 (append
433 (org-split-string org-e-beamer-frame-default-options ",")
434 (and beamer-opt
435 (org-split-string
436 ;; Remove square brackets if user provided
437 ;; them.
438 (and (string-match "^\\[?\\(.*\\)\\]?$" beamer-opt)
439 (match-string 1 beamer-opt))
440 ","))
441 ;; Provide an automatic label for the frame
442 ;; unless the user specified one.
443 (unless (and beamer-opt
444 (string-match "\\(^\\|,\\)label=" beamer-opt))
445 (list
446 (format "label=%s"
447 (org-e-beamer--get-label headline info)))))))
448 ;; Change options list into a string.
449 (org-e-beamer--normalize-argument
450 (mapconcat
451 'identity
452 (if (or (not fragilep) (member "fragile" options)) options
453 (cons "fragile" options))
454 ",")
455 'option))
456 ;; Title.
457 (format "{%s}"
458 (org-export-data (org-element-property :title headline)
459 info))
460 "\n"
461 ;; The following workaround is required in fragile frames
462 ;; as Beamer will append "\par" to the beginning of the
463 ;; contents. So we need to make sure the command is
464 ;; separated from the contents by at least one space. If
465 ;; it isn't, it will create "\parfirst-word" command and
466 ;; remove the first word from the contents in the PDF
467 ;; output.
468 (if (not fragilep) contents
469 (replace-regexp-in-string "\\`\n*" "\\& " contents))
470 "\\end{frame}")))
472 (defun org-e-beamer--format-block (headline contents info)
473 "Format HEADLINE as a block.
474 CONTENTS holds the contents of the headline. INFO is a plist
475 used as a communication channel."
476 (let* ((column-width (org-element-property :beamer-col headline))
477 ;; Environment defaults to "block" if none is specified and
478 ;; there is no column specification. If there is a column
479 ;; specified but still no explicit environment, ENVIRONMENT
480 ;; is nil.
481 (environment (let ((env (org-element-property :beamer-env headline)))
482 (cond
483 ;; "block" is the fallback environment.
484 ((and (not env) (not column-width)) "block")
485 ;; "column" only.
486 ((not env) nil)
487 ;; Use specified environment.
488 (t (downcase env)))))
489 (env-format (when environment
490 (assoc environment
491 (append org-e-beamer-environments-special
492 org-e-beamer-environments-extra
493 org-e-beamer-environments-default))))
494 (title (org-export-data (org-element-property :title headline) info))
495 ;; Start a columns environment when there is no previous
496 ;; headline or the previous headline do not have
497 ;; a BEAMER_column property.
498 (start-columns-p
499 (and column-width
500 (or (org-export-first-sibling-p headline info)
501 (not (org-element-property
502 :beamer-col
503 (org-export-get-previous-element headline info))))))
504 ;; Ends a columns environment when there is no next headline
505 ;; or the next headline do not have a BEAMER_column property.
506 (end-columns-p
507 (and column-width
508 (or (org-export-last-sibling-p headline info)
509 (not (org-element-property
510 :beamer-col
511 (org-export-get-next-element headline info)))))))
512 (concat
513 (when start-columns-p "\\begin{columns}\n")
514 (when column-width
515 (format "\\begin{column}%s{%s}\n"
516 ;; One can specify placement for column only when
517 ;; HEADLINE stands for a column on its own.
518 (if (not environment) ""
519 (let ((options (org-element-property :beamer-opt headline)))
520 (if (not options) ""
521 (org-e-beamer--normalize-argument options 'option))))
522 (format "%s\\textwidth" column-width)))
523 ;; Block's opening string.
524 (when env-format
525 (concat
526 (org-fill-template
527 (nth 2 env-format)
528 (nconc
529 ;; If BEAMER_act property has its value enclosed in square
530 ;; brackets, it is a default overlay specification and
531 ;; overlay specification is empty. Otherwise, it is an
532 ;; overlay specification and the default one is nil.
533 (let ((action (org-element-property :beamer-act headline)))
534 (cond
535 ((not action) (list (cons "a" "") (cons "A" "")))
536 ((string-match "\\`\\[.*\\]\\'" action)
537 (list
538 (cons "A"
539 (org-e-beamer--normalize-argument action 'defaction))
540 (cons "a" "")))
542 (list
543 (cons "a"
544 (org-e-beamer--normalize-argument action 'action))
545 (cons "A" "")))))
546 (list (cons "o"
547 (let ((options
548 (org-element-property :beamer-opt headline)))
549 (if (not options) ""
550 (org-e-beamer--normalize-argument options 'option))))
551 (cons "h" title)
552 (cons "H" (if (equal title "") "" (format "{%s}" title)))
553 (cons "U" (if (equal title "") "" (format "[%s]" title))))))
554 "\n"))
555 contents
556 ;; Block's closing string.
557 (when environment (concat (nth 3 env-format) "\n"))
558 (when column-width "\\end{column}\n")
559 (when end-columns-p "\\end{columns}"))))
561 (defun org-e-beamer-headline (headline contents info)
562 "Transcode HEADLINE element into Beamer code.
563 CONTENTS is the contents of the headline. INFO is a plist used
564 as a communication channel."
565 (unless (org-element-property :footnote-section-p headline)
566 (let ((level (org-export-get-relative-level headline info))
567 (frame-level (org-e-beamer--frame-level headline info))
568 (environment (let ((env (org-element-property :beamer-env headline)))
569 (if (stringp env) (downcase env) "block"))))
570 (cond
571 ;; Case 1: Resume frame specified by "BEAMER_ref" property.
572 ((equal environment "againframe")
573 (let ((ref (org-element-property :beamer-ref headline)))
574 ;; Reference to frame being resumed is mandatory. Ignore
575 ;; the whole headline if it isn't provided.
576 (when (org-string-nw-p ref)
577 (concat "\\againframe"
578 ;; Overlay specification.
579 (let ((overlay (org-element-property :beamer-act headline)))
580 (when overlay
581 (org-e-beamer--normalize-argument
582 overlay
583 (if (string-match "^\\[.*\\]$" overlay) 'defaction
584 'action))))
585 ;; Options.
586 (let ((options (org-element-property :beamer-opt headline)))
587 (when options
588 (org-e-beamer--normalize-argument options 'option)))
589 ;; Resolve reference provided by "BEAMER_ref"
590 ;; property. This is done by building a minimal fake
591 ;; link and calling the appropriate resolve function,
592 ;; depending on the reference syntax.
593 (let* ((type
594 (progn
595 (string-match "^\\(id:\\|#\\|\\*\\)?\\(.*\\)" ref)
596 (cond
597 ((or (not (match-string 1 ref))
598 (equal (match-string 1 ref) "*")) 'fuzzy)
599 ((equal (match-string 1 ref) "id:") 'id)
600 (t 'custom-id))))
601 (link (list 'link (list :path (match-string 2 ref))))
602 (target (if (eq type 'fuzzy)
603 (org-export-resolve-fuzzy-link link info)
604 (org-export-resolve-id-link link info))))
605 ;; Now use user-defined label provided in TARGET
606 ;; headline, or fallback to standard one.
607 (format "{%s}" (org-e-beamer--get-label target info)))))))
608 ;; Case 2: Creation of an appendix is requested.
609 ((equal environment "appendix")
610 (concat "\\appendix"
611 (org-element-property :beamer-act headline)
612 "\n"
613 (make-string (org-element-property :pre-blank headline) ?\n)
614 contents))
615 ;; Case 3: Ignore heading.
616 ((equal environment "ignoreheading")
617 (concat (make-string (org-element-property :pre-blank headline) ?\n)
618 contents))
619 ;; Case 4: HEADLINE is a note.
620 ((member environment '("note" "noteNH"))
621 (format "\\note{%s}"
622 (concat (and (equal environment "note")
623 (concat
624 (org-export-data
625 (org-element-property :title headline) info)
626 "\n"))
627 (org-trim contents))))
628 ;; Case 5: HEADLINE is a frame.
629 ((= level frame-level)
630 (org-e-beamer--format-frame headline contents info))
631 ;; Case 6: Regular section, extracted from
632 ;; `org-e-latex-classes'.
633 ((< level frame-level)
634 (org-e-beamer--format-section headline contents info))
635 ;; Case 7: Otherwise, HEADLINE is a block.
636 (t (org-e-beamer--format-block headline contents info))))))
639 ;;;; Item
641 (defun org-e-beamer-item (item contents info)
642 "Transcode an ITEM element into Beamer code.
643 CONTENTS holds the contents of the item. INFO is a plist holding
644 contextual information."
645 (let ((action (let ((first-element (car (org-element-contents item))))
646 (and (eq (org-element-type first-element) 'paragraph)
647 (org-e-beamer--element-has-overlay-p first-element))))
648 (output (funcall (cdr (assq 'item org-e-latex-translate-alist))
649 item contents info)))
650 (if (not action) output
651 ;; If the item starts with a paragraph and that paragraph starts
652 ;; with an export snippet specifying an overlay, insert it after
653 ;; \item command.
654 (replace-regexp-in-string "\\\\item" (concat "\\\\item" action) output))))
657 ;;;; Keyword
659 (defun org-e-beamer-keyword (keyword contents info)
660 "Transcode a KEYWORD element into Beamer code.
661 CONTENTS is nil. INFO is a plist used as a communication
662 channel."
663 (let ((key (org-element-property :key keyword))
664 (value (org-element-property :value keyword)))
665 ;; Handle specifically BEAMER and TOC (headlines only) keywords.
666 ;; Otherwise, fallback to `e-latex' back-end.
667 (cond
668 ((equal key "BEAMER") value)
669 ((and (equal key "TOC") (string-match "\\<headlines\\>" value))
670 (let ((depth (or (and (string-match "[0-9]+" value)
671 (string-to-number (match-string 0 value)))
672 (plist-get info :with-toc)))
673 (options (and (string-match "\\[.*?\\]" value)
674 (match-string 0 value))))
675 (concat
676 "\\begin{frame}"
677 (when (wholenump depth) (format "\\setcounter{tocdepth}{%s}\n" depth))
678 "\\tableofcontents" options "\n"
679 "\\end{frame}")))
680 (t (funcall (cdr (assq 'keyword org-e-latex-translate-alist))
681 keyword contents info)))))
684 ;;;; Link
686 (defun org-e-beamer-link (link contents info)
687 "Transcode a LINK object into Beamer code.
688 CONTENTS is the description part of the link. INFO is a plist
689 used as a communication channel."
690 (let ((type (org-element-property :type link))
691 (path (org-element-property :path link)))
692 ;; Use \hyperlink command for all internal links.
693 (cond
694 ((equal type "radio")
695 (let ((destination (org-export-resolve-radio-link link info)))
696 (when destination
697 (format "\\hyperlink%s{%s}{%s}"
698 (or (org-e-beamer--element-has-overlay-p link) "")
699 (org-export-solidify-link-text path)
700 (org-export-data (org-element-contents destination) info)))))
701 ((and (member type '("custom-id" "fuzzy" "id"))
702 (let ((destination (if (string= type "fuzzy")
703 (org-export-resolve-fuzzy-link link info)
704 (org-export-resolve-id-link link info))))
705 (case (org-element-type destination)
706 (headline
707 (let ((label
708 (format "sec-%s"
709 (mapconcat
710 'number-to-string
711 (org-export-get-headline-number
712 destination info)
713 "-"))))
714 (if (and (plist-get info :section-numbers) (not contents))
715 (format "\\ref{%s}" label)
716 (format "\\hyperlink%s{%s}{%s}"
717 (or (org-e-beamer--element-has-overlay-p link) "")
718 label
719 contents))))
720 (target
721 (let ((path (org-export-solidify-link-text path)))
722 (if (not contents) (format "\\ref{%s}" path)
723 (format "\\hyperlink%s{%s}{%s}"
724 (or (org-e-beamer--element-has-overlay-p link) "")
725 path
726 contents))))))))
727 ;; Otherwise, use `e-latex' back-end.
728 (t (funcall (cdr (assq 'link org-e-latex-translate-alist))
729 link contents info)))))
732 ;;;; Plain List
734 ;; Plain lists support `:overlay' (for any type), `:template' (for
735 ;; ordered lists only) and `:long-text' (for description lists only)
736 ;; attributes.
738 (defun org-e-beamer-plain-list (plain-list contents info)
739 "Transcode a PLAIN-LIST element into Beamer code.
740 CONTENTS is the contents of the list. INFO is a plist holding
741 contextual information."
742 (let* ((type (org-element-property :type plain-list))
743 (attributes (org-export-read-attribute :attr_beamer plain-list))
744 (latex-type (cond ((eq type 'ordered) "enumerate")
745 ((eq type 'descriptive) "description")
746 (t "itemize"))))
747 (org-e-latex--wrap-label
748 plain-list
749 (format "\\begin{%s}%s%s\n%s\\end{%s}"
750 latex-type
751 ;; Default overlay specification, if any.
752 (let ((overlay (plist-get attributes :overlay)))
753 (if (not overlay) ""
754 (org-e-beamer--normalize-argument overlay 'defaction)))
755 ;; Second optional argument depends on the list type.
756 (case type
757 (ordered
758 (let ((template (plist-get attributes :template)))
759 (if (not template) ""
760 (org-e-beamer--normalize-argument template 'option))))
761 (descriptive
762 (let ((long-text (plist-get attributes :long-text)))
763 (if (not long-text) ""
764 (org-e-beamer--normalize-argument long-text 'option))))
765 ;; There's no second argument for un-ordered lists.
766 (otherwise ""))
767 ;; Eventually insert contents and close environment.
768 contents
769 latex-type))))
772 ;;;; Radio Target
774 (defun org-e-beamer-radio-target (radio-target text info)
775 "Transcode a RADIO-TARGET object into Beamer code.
776 TEXT is the text of the target. INFO is a plist holding
777 contextual information."
778 (format "\\hypertarget%s{%s}{%s}"
779 (or (org-e-beamer--element-has-overlay-p radio-target) "")
780 (org-export-solidify-link-text
781 (org-element-property :value radio-target))
782 text))
785 ;;;; Target
787 (defun org-e-beamer-target (target contents info)
788 "Transcode a TARGET object into Beamer code.
789 CONTENTS is nil. INFO is a plist holding contextual
790 information."
791 (format "\\hypertarget{%s}{}"
792 (org-export-solidify-link-text (org-element-property :value target))))
795 ;;;; Template
797 ;; Template used is similar to the one used in `e-latex' back-end,
798 ;; excepted for the table of contents and Beamer themes.
800 (defun org-e-beamer-template (contents info)
801 "Return complete document string after Beamer conversion.
802 CONTENTS is the transcoded contents string. INFO is a plist
803 holding export options."
804 (let ((title (org-export-data (plist-get info :title) info)))
805 (concat
806 ;; 1. Time-stamp.
807 (and (plist-get info :time-stamp-file)
808 (format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
809 ;; 2. Document class and packages.
810 (let ((class (plist-get info :latex-class))
811 (class-options (plist-get info :latex-class-options)))
812 (org-element-normalize-string
813 (let* ((header (nth 1 (assoc class org-e-latex-classes)))
814 (document-class-string
815 (and (stringp header)
816 (if (not class-options) header
817 (replace-regexp-in-string
818 "^[ \t]*\\\\documentclass\\(\\(\\[.*\\]\\)?\\)"
819 class-options header t nil 1)))))
820 (when document-class-string
821 (org-e-latex--guess-babel-language
822 (org-e-latex--guess-inputenc
823 (org-splice-latex-header
824 document-class-string
825 org-export-latex-default-packages-alist ; defined in org.el
826 org-export-latex-packages-alist nil ; defined in org.el
827 (plist-get info :latex-header-extra)))
828 info)))))
829 ;; 3. Insert themes.
830 (let ((format-theme
831 (function
832 (lambda (prop command)
833 (let ((theme (plist-get info prop)))
834 (when theme
835 (concat command
836 (if (not (string-match "\\[.*\\]" theme))
837 (format "{%s}\n" theme)
838 (format "%s{%s}\n"
839 (match-string 0 theme)
840 (org-trim
841 (replace-match "" nil nil theme)))))))))))
842 (mapconcat (lambda (args) (apply format-theme args))
843 '((:beamer-theme "\\usetheme")
844 (:beamer-color-theme "\\usecolortheme")
845 (:beamer-font-theme "\\usefonttheme")
846 (:beamer-inner-theme "\\useinnertheme")
847 (:beamer-outer-theme "\\useoutertheme"))
848 ""))
849 ;; 4. Possibly limit depth for headline numbering.
850 (let ((sec-num (plist-get info :section-numbers)))
851 (when (integerp sec-num)
852 (format "\\setcounter{secnumdepth}{%d}\n" sec-num)))
853 ;; 5. Author.
854 (let ((author (and (plist-get info :with-author)
855 (let ((auth (plist-get info :author)))
856 (and auth (org-export-data auth info)))))
857 (email (and (plist-get info :with-email)
858 (org-export-data (plist-get info :email) info))))
859 (cond ((and author email (not (string= "" email)))
860 (format "\\author{%s\\thanks{%s}}\n" author email))
861 (author (format "\\author{%s}\n" author))
862 (t "\\author{}\n")))
863 ;; 6. Date.
864 (format "\\date{%s}\n" (org-export-data (plist-get info :date) info))
865 ;; 7. Title
866 (format "\\title{%s}\n" title)
867 ;; 8. Hyperref options.
868 (format "\\hypersetup{\n pdfkeywords={%s},\n pdfsubject={%s},\n pdfcreator={%s}}\n"
869 (or (plist-get info :keywords) "")
870 (or (plist-get info :description) "")
871 (if (not (plist-get info :with-creator)) ""
872 (plist-get info :creator)))
873 ;; 9. Document start.
874 "\\begin{document}\n\n"
875 ;; 10. Title command.
876 (org-element-normalize-string
877 (cond ((string= "" title) nil)
878 ((not (stringp org-e-latex-title-command)) nil)
879 ((string-match "\\(?:[^%]\\|^\\)%s"
880 org-e-latex-title-command)
881 (format org-e-latex-title-command title))
882 (t org-e-latex-title-command)))
883 ;; 11. Table of contents.
884 (let ((depth (plist-get info :with-toc)))
885 (when depth
886 (concat
887 (format "\\begin{frame}%s{%s}\n"
888 (org-e-beamer--normalize-argument
889 org-e-beamer-outline-frame-options 'option)
890 org-e-beamer-outline-frame-title)
891 (when (wholenump depth)
892 (format "\\setcounter{tocdepth}{%d}\n" depth))
893 "\\tableofcontents\n"
894 "\\end{frame}\n\n")))
895 ;; 12. Document's body.
896 contents
897 ;; 13. Creator.
898 (let ((creator-info (plist-get info :with-creator)))
899 (cond
900 ((not creator-info) "")
901 ((eq creator-info 'comment)
902 (format "%% %s\n" (plist-get info :creator)))
903 (t (concat (plist-get info :creator) "\n"))))
904 ;; 14. Document end.
905 "\\end{document}")))
909 ;;; Minor Mode
912 (defvar org-e-beamer-mode-map (make-sparse-keymap)
913 "The keymap for `org-e-beamer-mode'.")
914 (define-key org-e-beamer-mode-map "\C-c\C-b" 'org-e-beamer-select-environment)
916 ;;;###autoload
917 (define-minor-mode org-e-beamer-mode
918 "Support for editing Beamer oriented Org mode files."
919 nil " Bm" 'org-e-beamer-mode-map)
921 (when (fboundp 'font-lock-add-keywords)
922 (font-lock-add-keywords
923 'org-mode
924 '((":\\(B_[a-z]+\\|BMCOL\\):" 1 'org-e-beamer-tag prepend))
925 'prepend))
927 (defface org-e-beamer-tag '((t (:box (:line-width 1 :color grey40))))
928 "The special face for beamer tags."
929 :group 'org-export-e-beamer)
931 (defun org-e-beamer-property-changed (property value)
932 "Track the BEAMER_env property with tags.
933 PROPERTY is the name of the modified property. VALUE is its new
934 value."
935 (cond
936 ((equal property "BEAMER_env")
937 (save-excursion
938 (org-back-to-heading t)
939 ;; Filter out Beamer-related tags and install environment tag.
940 (let ((tags (org-remove-if (lambda (x) (string-match "^B_" x))
941 (org-get-tags)))
942 (env-tag (and (org-string-nw-p value) (concat "B_" value))))
943 (org-set-tags-to (if env-tag (cons env-tag tags) tags))
944 (when env-tag (org-toggle-tag env-tag 'on)))))
945 ((equal property "BEAMER_col")
946 (org-toggle-tag "BMCOL" (if (org-string-nw-p value) 'on 'off)))))
948 (add-hook 'org-property-changed-functions 'org-e-beamer-property-changed)
950 (defun org-e-beamer-allowed-property-values (property)
951 "Supply allowed values for PROPERTY."
952 (cond
953 ((and (equal property "BEAMER_env")
954 (not (org-entry-get nil (concat property "_ALL") 'inherit)))
955 ;; If no allowed values for BEAMER_env have been defined,
956 ;; supply all defined environments
957 (mapcar 'car (append org-e-beamer-environments-special
958 org-e-beamer-environments-extra
959 org-e-beamer-environments-default)))
960 ((and (equal property "BEAMER_col")
961 (not (org-entry-get nil (concat property "_ALL") 'inherit)))
962 ;; If no allowed values for BEAMER_col have been defined,
963 ;; supply some
964 (org-split-string org-e-beamer-column-widths " "))))
966 (add-hook 'org-property-allowed-value-functions
967 'org-e-beamer-allowed-property-values)
971 ;;; Commands
973 ;;;###autoload
974 (defun org-e-beamer-export-as-latex
975 (&optional subtreep visible-only body-only ext-plist)
976 "Export current buffer as a Beamer buffer.
978 If narrowing is active in the current buffer, only export its
979 narrowed part.
981 If a region is active, export that region.
983 When optional argument SUBTREEP is non-nil, export the sub-tree
984 at point, extracting information from the headline properties
985 first.
987 When optional argument VISIBLE-ONLY is non-nil, don't export
988 contents of hidden elements.
990 When optional argument BODY-ONLY is non-nil, only write code
991 between \"\\begin{document}\" and \"\\end{document}\".
993 EXT-PLIST, when provided, is a property list with external
994 parameters overriding Org default settings, but still inferior to
995 file-local settings.
997 Export is done in a buffer named \"*Org E-BEAMER Export*\", which
998 will be displayed when `org-export-show-temporary-export-buffer'
999 is non-nil."
1000 (interactive)
1001 (let ((outbuf (org-export-to-buffer
1002 'e-beamer "*Org E-BEAMER Export*"
1003 subtreep visible-only body-only ext-plist)))
1004 (with-current-buffer outbuf (LaTeX-mode))
1005 (when org-export-show-temporary-export-buffer
1006 (switch-to-buffer-other-window outbuf))))
1008 ;;;###autoload
1009 (defun org-e-beamer-export-to-latex
1010 (&optional subtreep visible-only body-only ext-plist pub-dir)
1011 "Export current buffer as a Beamer presentation (tex).
1013 If narrowing is active in the current buffer, only export its
1014 narrowed part.
1016 If a region is active, export that region.
1018 When optional argument SUBTREEP is non-nil, export the sub-tree
1019 at point, extracting information from the headline properties
1020 first.
1022 When optional argument VISIBLE-ONLY is non-nil, don't export
1023 contents of hidden elements.
1025 When optional argument BODY-ONLY is non-nil, only write code
1026 between \"\\begin{document}\" and \"\\end{document}\".
1028 EXT-PLIST, when provided, is a property list with external
1029 parameters overriding Org default settings, but still inferior to
1030 file-local settings.
1032 When optional argument PUB-DIR is set, use it as the publishing
1033 directory.
1035 Return output file's name."
1036 (interactive)
1037 (let ((outfile (org-export-output-file-name ".tex" subtreep pub-dir)))
1038 (org-export-to-file
1039 'e-beamer outfile subtreep visible-only body-only ext-plist)))
1041 ;;;###autoload
1042 (defun org-e-beamer-export-to-pdf
1043 (&optional subtreep visible-only body-only ext-plist pub-dir)
1044 "Export current buffer as a Beamer presentation (PDF).
1046 If narrowing is active in the current buffer, only export its
1047 narrowed part.
1049 If a region is active, export that region.
1051 When optional argument SUBTREEP is non-nil, export the sub-tree
1052 at point, extracting information from the headline properties
1053 first.
1055 When optional argument VISIBLE-ONLY is non-nil, don't export
1056 contents of hidden elements.
1058 When optional argument BODY-ONLY is non-nil, only write code
1059 between \"\\begin{document}\" and \"\\end{document}\".
1061 EXT-PLIST, when provided, is a property list with external
1062 parameters overriding Org default settings, but still inferior to
1063 file-local settings.
1065 When optional argument PUB-DIR is set, use it as the publishing
1066 directory.
1068 Return PDF file's name."
1069 (interactive)
1070 (org-e-latex-compile
1071 (org-e-beamer-export-to-latex
1072 subtreep visible-only body-only ext-plist pub-dir)))
1074 ;;;###autoload
1075 (defun org-e-beamer-select-environment ()
1076 "Select the environment to be used by beamer for this entry.
1077 While this uses (for convenience) a tag selection interface, the
1078 result of this command will be that the BEAMER_env *property* of
1079 the entry is set.
1081 In addition to this, the command will also set a tag as a visual
1082 aid, but the tag does not have any semantic meaning."
1083 (interactive)
1084 ;; Make sure `org-e-beamer-environments-special' has a higher
1085 ;; priority than `org-e-beamer-environments-extra'.
1086 (let* ((envs (append org-e-beamer-environments-special
1087 org-e-beamer-environments-extra
1088 org-e-beamer-environments-default))
1089 (org-tag-alist
1090 (append '((:startgroup))
1091 (mapcar (lambda (e) (cons (concat "B_" (car e))
1092 (string-to-char (nth 1 e))))
1093 envs)
1094 '((:endgroup))
1095 '(("BMCOL" . ?|))))
1096 (org-fast-tag-selection-single-key t))
1097 (org-set-tags)
1098 (let ((tags (or (ignore-errors (org-get-tags-string)) "")))
1099 (cond
1100 ;; For a column, automatically ask for its width.
1101 ((eq org-last-tag-selection-key ?|)
1102 (if (string-match ":BMCOL:" tags)
1103 (org-set-property "BEAMER_col" (read-string "Column width: "))
1104 (org-delete-property "BEAMER_col")))
1105 ;; For an "againframe" section, automatically ask for reference
1106 ;; to resumed frame and overlay specifications.
1107 ((eq org-last-tag-selection-key ?F)
1108 (if (equal (org-entry-get nil "BEAMER_env") "againframe")
1109 (progn (org-entry-delete nil "BEAMER_env")
1110 (org-entry-delete nil "BEAMER_ref")
1111 (org-entry-delete nil "BEAMER_act"))
1112 (org-entry-put nil "BEAMER_env" "againframe")
1113 (org-set-property
1114 "BEAMER_ref"
1115 (read-string "Frame reference (*Title, #custom-id, id:...): "))
1116 (org-set-property "BEAMER_act"
1117 (read-string "Overlay specification: "))))
1118 ((string-match (concat ":B_\\(" (mapconcat 'car envs "\\|") "\\):") tags)
1119 (org-entry-put nil "BEAMER_env" (match-string 1 tags)))
1120 (t (org-entry-delete nil "BEAMER_env"))))))
1122 ;;;###autoload
1123 (defun org-e-beamer-insert-options-template (&optional kind)
1124 "Insert a settings template, to make sure users do this right."
1125 (interactive (progn
1126 (message "Current [s]ubtree or [g]lobal?")
1127 (if (eq (read-char-exclusive) ?g) (list 'global)
1128 (list 'subtree))))
1129 (if (eq kind 'subtree)
1130 (progn
1131 (org-back-to-heading t)
1132 (org-reveal)
1133 (org-entry-put nil "EXPORT_LaTeX_CLASS" "beamer")
1134 (org-entry-put nil "EXPORT_LaTeX_CLASS_OPTIONS" "[presentation]")
1135 (org-entry-put nil "EXPORT_FILE_NAME" "presentation.pdf")
1136 (when org-e-beamer-column-view-format
1137 (org-entry-put nil "COLUMNS" org-e-beamer-column-view-format))
1138 (org-entry-put nil "BEAMER_col_ALL" org-e-beamer-column-widths))
1139 (insert "#+LaTeX_CLASS: beamer\n")
1140 (insert "#+LaTeX_CLASS_OPTIONS: [presentation]\n")
1141 (when org-e-beamer-theme
1142 (insert "#+BEAMER_THEME: " org-e-beamer-theme "\n"))
1143 (when org-e-beamer-column-view-format
1144 (insert "#+COLUMNS: " org-e-beamer-column-view-format "\n"))
1145 (insert "#+PROPERTY: BEAMER_col_ALL " org-e-beamer-column-widths "\n")))
1148 (provide 'org-e-beamer)
1149 ;;; org-e-beamer.el ends here