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