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