Commit | Line | Data |
---|---|---|
db9c3fb1 | 1 | ;;; org-export-latex.el --- LaTeX exporter for org-mode |
72a81656 | 2 | ;; |
b1fc2b50 | 3 | ;; Copyright (C) 2007, 2008 Free Software Foundation, Inc. |
15841868 JW |
4 | ;; |
5 | ;; Emacs Lisp Archive Entry | |
6 | ;; Filename: org-export-latex.el | |
ce4fdcb9 | 7 | ;; Version: 6.13 |
72a81656 | 8 | ;; Author: Bastien Guerry <bzg AT altern DOT org> |
15841868 JW |
9 | ;; Maintainer: Bastien Guerry <bzg AT altern DOT org> |
10 | ;; Keywords: org, wp, tex | |
11 | ;; Description: Converts an org-mode buffer into LaTeX | |
12 | ;; URL: http://www.cognition.ens.fr/~guerry/u/org-export-latex.el | |
b1fc2b50 | 13 | |
72a81656 | 14 | ;; This file is part of GNU Emacs. |
b1fc2b50 GM |
15 | |
16 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
17 | ;; it under the terms of the GNU General Public License as published by | |
18 | ;; the Free Software Foundation, either version 3 of the License, or | |
19 | ;; (at your option) any later version. | |
20 | ||
21 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
22 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | ;; GNU General Public License for more details. | |
25 | ||
db9c3fb1 | 26 | ;; You should have received a copy of the GNU General Public License |
b1fc2b50 GM |
27 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
28 | ||
72a81656 | 29 | ;;; Commentary: |
0b8568f5 JW |
30 | ;; |
31 | ;; This library implements a LaTeX exporter for org-mode. | |
db9c3fb1 | 32 | ;; |
72a81656 CD |
33 | ;; Put this file into your load-path and the following into your ~/.emacs: |
34 | ;; (require 'org-export-latex) | |
db9c3fb1 | 35 | ;; |
72a81656 | 36 | ;; The interactive functions are similar to those of the HTML exporter: |
db9c3fb1 | 37 | ;; |
72a81656 | 38 | ;; M-x `org-export-as-latex' |
71d35b24 CD |
39 | ;; M-x `org-export-as-pdf' |
40 | ;; M-x `org-export-as-pdf-and-open' | |
72a81656 CD |
41 | ;; M-x `org-export-as-latex-batch' |
42 | ;; M-x `org-export-as-latex-to-buffer' | |
43 | ;; M-x `org-export-region-as-latex' | |
44 | ;; M-x `org-replace-region-by-latex' | |
4b67ea89 | 45 | ;; |
72a81656 CD |
46 | ;;; Code: |
47 | ||
0b8568f5 JW |
48 | (eval-when-compile |
49 | (require 'cl)) | |
50 | ||
72a81656 | 51 | (require 'footnote) |
0b8568f5 | 52 | (require 'org) |
20908596 | 53 | (require 'org-exp) |
72a81656 | 54 | |
0b8568f5 | 55 | ;;; Variables: |
db9c3fb1 CD |
56 | (defvar org-export-latex-class nil) |
57 | (defvar org-export-latex-header nil) | |
58 | (defvar org-export-latex-append-header nil) | |
59 | (defvar org-export-latex-options-plist nil) | |
60 | (defvar org-export-latex-todo-keywords-1 nil) | |
61 | (defvar org-export-latex-all-targets-re nil) | |
62 | (defvar org-export-latex-add-level 0) | |
63 | (defvar org-export-latex-sectioning "") | |
64 | (defvar org-export-latex-sectioning-depth 0) | |
db9c3fb1 | 65 | (defvar org-export-latex-special-string-regexps |
72a81656 CD |
66 | '(org-ts-regexp |
67 | org-scheduled-string | |
68 | org-deadline-string | |
69 | org-clock-string) | |
70 | "A list of regexps to convert as special keywords.") | |
71 | ||
0b8568f5 JW |
72 | (defvar latexp) ; dynamically scoped from org.el |
73 | (defvar re-quote) ; dynamically scoped from org.el | |
74 | (defvar commentsp) ; dynamically scoped from org.el | |
75 | ||
db9c3fb1 | 76 | ;;; User variables: |
72a81656 | 77 | |
621f83e4 CD |
78 | (defgroup org-export-latex nil |
79 | "Options for exporting Org-mode files to LaTeX." | |
80 | :tag "Org Export LaTeX" | |
81 | :group 'org-export) | |
82 | ||
db9c3fb1 CD |
83 | (defcustom org-export-latex-default-class "article" |
84 | "The default LaTeX class." | |
85 | :group 'org-export-latex | |
86 | :type '(string :tag "LaTeX class")) | |
72a81656 | 87 | |
db9c3fb1 CD |
88 | (defcustom org-export-latex-classes |
89 | '(("article" | |
90 | "\\documentclass[11pt,a4paper]{article} | |
91 | \\usepackage[utf8]{inputenc} | |
92 | \\usepackage[T1]{fontenc} | |
71d35b24 | 93 | \\usepackage{graphicx} |
db9c3fb1 CD |
94 | \\usepackage{hyperref}" |
95 | ("\\section{%s}" . "\\section*{%s}") | |
96 | ("\\subsection{%s}" . "\\subsection*{%s}") | |
97 | ("\\subsubsection{%s}" . "\\subsubsection*{%s}") | |
98 | ("\\paragraph{%s}" . "\\paragraph*{%s}") | |
99 | ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) | |
100 | ("report" | |
101 | "\\documentclass[11pt,a4paper]{report} | |
102 | \\usepackage[utf8]{inputenc} | |
103 | \\usepackage[T1]{fontenc} | |
71d35b24 | 104 | \\usepackage{graphicx} |
db9c3fb1 CD |
105 | \\usepackage{hyperref}" |
106 | ("\\part{%s}" . "\\part*{%s}") | |
107 | ("\\chapter{%s}" . "\\chapter*{%s}") | |
108 | ("\\section{%s}" . "\\section*{%s}") | |
109 | ("\\subsection{%s}" . "\\subsection*{%s}") | |
110 | ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) | |
111 | ("book" | |
112 | "\\documentclass[11pt,a4paper]{book} | |
113 | \\usepackage[utf8]{inputenc} | |
114 | \\usepackage[T1]{fontenc} | |
71d35b24 | 115 | \\usepackage{graphicx} |
db9c3fb1 CD |
116 | \\usepackage{hyperref}" |
117 | ("\\part{%s}" . "\\part*{%s}") | |
118 | ("\\chapter{%s}" . "\\chapter*{%s}") | |
119 | ("\\section{%s}" . "\\section*{%s}") | |
120 | ("\\subsection{%s}" . "\\subsection*{%s}") | |
121 | ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) | |
122 | "Alist of LaTeX classes and associated header and structure. | |
123 | If #+LaTeX_CLASS is set in the buffer, use its value and the | |
124 | associated information. Here is the structure of each cell: | |
125 | ||
126 | \(class-name | |
127 | header-string | |
71d35b24 | 128 | (numbered-section . unnumbered-section\) |
db9c3fb1 CD |
129 | ...\) |
130 | ||
131 | A %s formatter is mandatory in each section string and will be | |
71d35b24 CD |
132 | replaced by the title of the section. |
133 | ||
134 | Instead of a cons cell (numbered . unnumbered), you can also provide a list | |
135 | of 2-4 elements, | |
136 | ||
137 | (numbered-open numbered-close) | |
138 | ||
139 | or | |
140 | ||
141 | (numbered-open numbered-close unnumbered-open unnumbered-close) | |
142 | ||
143 | providing opening and closing strings for an environment that should | |
144 | represent the document section. The opening clause should have a %s | |
145 | to represent the section title." | |
72a81656 | 146 | :group 'org-export-latex |
71d35b24 | 147 | :type '(repeat |
db9c3fb1 CD |
148 | (list (string :tag "LaTeX class") |
149 | (string :tag "LaTeX header") | |
71d35b24 CD |
150 | (repeat :tag "Levels" :inline t |
151 | (choice | |
152 | (cons :tag "Heading" | |
153 | (string :tag "numbered") | |
154 | (string :tag "unnumbered)")) | |
155 | (list :tag "Environment" | |
156 | (string :tag "Opening (numbered) ") | |
157 | (string :tag "Closing (numbered) ") | |
158 | (string :tag "Opening (unnumbered)") | |
159 | (string :tag "Closing (unnumbered)"))))))) | |
72a81656 CD |
160 | |
161 | (defcustom org-export-latex-emphasis-alist | |
15841868 JW |
162 | '(("*" "\\textbf{%s}" nil) |
163 | ("/" "\\emph{%s}" nil) | |
164 | ("_" "\\underline{%s}" nil) | |
165 | ("+" "\\texttt{%s}" nil) | |
db9c3fb1 CD |
166 | ("=" "\\texttt{%s}" nil) |
167 | ("~" "\\texttt{%s}" t)) | |
15841868 JW |
168 | "Alist of LaTeX expressions to convert emphasis fontifiers. |
169 | Each element of the list is a list of three elements. | |
170 | The first element is the character used as a marker for fontification. | |
171 | The second element is a formatting string to wrap fontified text with. | |
172 | The third element decides whether to protect converted text from other | |
173 | conversions." | |
72a81656 CD |
174 | :group 'org-export-latex |
175 | :type 'alist) | |
176 | ||
15841868 JW |
177 | (defcustom org-export-latex-title-command "\\maketitle" |
178 | "The command used to insert the title just after \\begin{document}. | |
179 | If this string contains the formatting specification \"%s\" then | |
180 | it will be used as a formatting string, passing the title as an | |
181 | argument." | |
182 | :group 'org-export-latex | |
183 | :type 'string) | |
184 | ||
db9c3fb1 | 185 | (defcustom org-export-latex-date-format |
d5098885 | 186 | "%d %B %Y" |
72a81656 CD |
187 | "Format string for \\date{...}." |
188 | :group 'org-export-latex | |
189 | :type 'string) | |
190 | ||
d5098885 | 191 | (defcustom org-export-latex-tables-verbatim nil |
621f83e4 | 192 | "When non-nil, tables are exported verbatim." |
d5098885 JW |
193 | :group 'org-export-latex |
194 | :type 'boolean) | |
195 | ||
db9c3fb1 | 196 | (defcustom org-export-latex-tables-column-borders nil |
621f83e4 | 197 | "When non-nil, group of columns are surrounded with borders." |
db9c3fb1 CD |
198 | :group 'org-export-latex |
199 | :type 'boolean) | |
72a81656 | 200 | |
db9c3fb1 CD |
201 | (defcustom org-export-latex-packages-alist nil |
202 | "Alist of packages to be inserted in the header. | |
203 | Each cell is of the forma \( \"option\" . \"package\" \)." | |
72a81656 CD |
204 | :group 'org-export-latex |
205 | :type 'alist) | |
206 | ||
207 | (defcustom org-export-latex-low-levels 'description | |
621f83e4 CD |
208 | "How to convert sections below the current level of sectioning. |
209 | This is specified by the `org-export-headline-levels' option or the | |
210 | value of \"H:\" in Org's #+OPTION line. | |
15841868 JW |
211 | |
212 | This can be either nil (skip the sections), 'description (convert | |
213 | the sections as descriptive lists) or a string to be used instead | |
214 | of \\section{%s}. In this latter case, the %s stands here for the | |
215 | inserted headline and is mandatory." | |
72a81656 CD |
216 | :group 'org-export-latex |
217 | :type '(choice (const :tag "Ignore" nil) | |
218 | (symbol :tag "Convert as descriptive list" description) | |
219 | (string :tag "Use a section string" :value "\\subparagraph{%s}"))) | |
220 | ||
d5098885 | 221 | (defcustom org-export-latex-remove-from-headlines |
72a81656 CD |
222 | '(:todo t :priority t :tags t) |
223 | "A plist of keywords to remove from headlines. | |
224 | Non-nil means remove this keyword type from the headline. | |
225 | ||
226 | Don't remove the keys, just change their values." | |
227 | :type 'plist | |
228 | :group 'org-export-latex) | |
229 | ||
72a81656 CD |
230 | (defcustom org-export-latex-image-default-option "width=10em" |
231 | "Default option for images." | |
232 | :group 'org-export-latex | |
db9c3fb1 | 233 | :type 'string) |
72a81656 CD |
234 | |
235 | (defcustom org-export-latex-coding-system nil | |
236 | "Coding system for the exported LaTex file." | |
237 | :group 'org-export-latex | |
238 | :type 'coding-system) | |
239 | ||
71d35b24 CD |
240 | (defgroup org-export-pdf nil |
241 | "Options for exporting Org-mode files to PDF, via LaTeX." | |
242 | :tag "Org Export LaTeX" | |
243 | :group 'org-export-latex | |
244 | :group 'org-export) | |
245 | ||
246 | (defcustom org-export-pdf-remove-logfiles t | |
247 | "Non-nil means, remove the logfiles produced by PDF production. | |
248 | These are the .aux, .log, .out, and .toc files." | |
249 | :group 'org-export-latex | |
250 | :type 'boolean) | |
251 | ||
0b8568f5 | 252 | ;;; Autoload functions: |
db9c3fb1 | 253 | |
72a81656 CD |
254 | ;;;###autoload |
255 | (defun org-export-as-latex-batch () | |
621f83e4 CD |
256 | "Call `org-export-as-latex', may be used in batch processing. |
257 | For example: | |
258 | ||
72a81656 CD |
259 | emacs --batch |
260 | --load=$HOME/lib/emacs/org.el | |
261 | --eval \"(setq org-export-headline-levels 2)\" | |
262 | --visit=MyFile --funcall org-export-as-latex-batch" | |
263 | (org-export-as-latex org-export-headline-levels 'hidden)) | |
264 | ||
265 | ;;;###autoload | |
266 | (defun org-export-as-latex-to-buffer (arg) | |
267 | "Call `org-exort-as-latex` with output to a temporary buffer. | |
268 | No file is created. The prefix ARG is passed through to `org-export-as-latex'." | |
269 | (interactive "P") | |
270 | (org-export-as-latex arg nil nil "*Org LaTeX Export*") | |
271 | (switch-to-buffer-other-window "*Org LaTeX Export*")) | |
272 | ||
273 | ;;;###autoload | |
274 | (defun org-replace-region-by-latex (beg end) | |
275 | "Replace the region from BEG to END with its LaTeX export. | |
276 | It assumes the region has `org-mode' syntax, and then convert it to | |
db9c3fb1 | 277 | LaTeX. This can be used in any buffer. For example, you could |
72a81656 CD |
278 | write an itemized list in `org-mode' syntax in an LaTeX buffer and |
279 | then use this command to convert it." | |
280 | (interactive "r") | |
281 | (let (reg latex buf) | |
282 | (save-window-excursion | |
283 | (if (org-mode-p) | |
284 | (setq latex (org-export-region-as-latex | |
285 | beg end t 'string)) | |
286 | (setq reg (buffer-substring beg end) | |
287 | buf (get-buffer-create "*Org tmp*")) | |
288 | (save-excursion | |
289 | (set-buffer buf) | |
290 | (erase-buffer) | |
291 | (insert reg) | |
292 | (org-mode) | |
293 | (setq latex (org-export-region-as-latex | |
294 | (point-min) (point-max) t 'string))) | |
295 | (kill-buffer buf))) | |
296 | (delete-region beg end) | |
297 | (insert latex))) | |
298 | ||
299 | ;;;###autoload | |
300 | (defun org-export-region-as-latex (beg end &optional body-only buffer) | |
301 | "Convert region from BEG to END in `org-mode' buffer to LaTeX. | |
302 | If prefix arg BODY-ONLY is set, omit file header, footer, and table of | |
303 | contents, and only produce the region of converted text, useful for | |
304 | cut-and-paste operations. | |
305 | If BUFFER is a buffer or a string, use/create that buffer as a target | |
306 | of the converted LaTeX. If BUFFER is the symbol `string', return the | |
307 | produced LaTeX as a string and leave not buffer behind. For example, | |
308 | a Lisp program could call this function in the following way: | |
309 | ||
310 | (setq latex (org-export-region-as-latex beg end t 'string)) | |
311 | ||
312 | When called interactively, the output buffer is selected, and shown | |
313 | in a window. A non-interactive call will only retunr the buffer." | |
314 | (interactive "r\nP") | |
315 | (when (interactive-p) | |
316 | (setq buffer "*Org LaTeX Export*")) | |
317 | (let ((transient-mark-mode t) (zmacs-regions t) | |
318 | rtn) | |
319 | (goto-char end) | |
320 | (set-mark (point)) ;; to activate the region | |
321 | (goto-char beg) | |
322 | (setq rtn (org-export-as-latex | |
323 | nil nil nil | |
324 | buffer body-only)) | |
325 | (if (fboundp 'deactivate-mark) (deactivate-mark)) | |
326 | (if (and (interactive-p) (bufferp rtn)) | |
327 | (switch-to-buffer-other-window rtn) | |
328 | rtn))) | |
329 | ||
330 | ;;;###autoload | |
331 | (defun org-export-as-latex (arg &optional hidden ext-plist | |
4b67ea89 | 332 | to-buffer body-only pub-dir) |
db9c3fb1 CD |
333 | "Export current buffer to a LaTeX file. |
334 | If there is an active region, export only the region. The prefix | |
335 | ARG specifies how many levels of the outline should become | |
336 | headlines. The default is 3. Lower levels will be exported | |
337 | depending on `org-export-latex-low-levels'. The default is to | |
338 | convert them as description lists. When HIDDEN is non-nil, don't | |
339 | display the LaTeX buffer. EXT-PLIST is a property list with | |
340 | external parameters overriding org-mode's default settings, but | |
341 | still inferior to file-local settings. When TO-BUFFER is | |
342 | non-nil, create a buffer with that name and export to that | |
343 | buffer. If TO-BUFFER is the symbol `string', don't leave any | |
344 | buffer behind but just return the resulting LaTeX as a string. | |
345 | When BODY-ONLY is set, don't produce the file header and footer, | |
346 | simply return the content of \begin{document}...\end{document}, | |
4b67ea89 CD |
347 | without even the \begin{document} and \end{document} commands. |
348 | when PUB-DIR is set, use this as the publishing directory." | |
72a81656 CD |
349 | (interactive "P") |
350 | ;; Make sure we have a file name when we need it. | |
351 | (when (and (not (or to-buffer body-only)) | |
352 | (not buffer-file-name)) | |
353 | (if (buffer-base-buffer) | |
354 | (org-set-local 'buffer-file-name | |
355 | (with-current-buffer (buffer-base-buffer) | |
356 | buffer-file-name)) | |
357 | (error "Need a file name to be able to export"))) | |
358 | ||
359 | (message "Exporting to LaTeX...") | |
360 | (org-update-radio-target-regexp) | |
db9c3fb1 | 361 | (org-export-latex-set-initial-vars ext-plist arg) |
15841868 | 362 | (let* ((wcf (current-window-configuration)) |
db9c3fb1 CD |
363 | (opt-plist org-export-latex-options-plist) |
364 | (region-p (org-region-active-p)) | |
b349f79f CD |
365 | (rbeg (and region-p (region-beginning))) |
366 | (rend (and region-p (region-end))) | |
db9c3fb1 CD |
367 | (subtree-p |
368 | (when region-p | |
369 | (save-excursion | |
b349f79f | 370 | (goto-char rbeg) |
db9c3fb1 | 371 | (and (org-at-heading-p) |
b349f79f | 372 | (>= (org-end-of-subtree t t) rend))))) |
621f83e4 | 373 | (opt-plist (if subtree-p |
b349f79f CD |
374 | (org-export-add-subtree-options opt-plist rbeg) |
375 | opt-plist)) | |
376 | ;; Make sure the variable contains the updated values. | |
377 | (org-export-latex-options-plist opt-plist) | |
db9c3fb1 CD |
378 | (title (or (and subtree-p (org-export-get-title-from-subtree)) |
379 | (plist-get opt-plist :title) | |
380 | (and (not | |
381 | (plist-get opt-plist :skip-before-1st-heading)) | |
382 | (org-export-grab-title-from-buffer)) | |
383 | (file-name-sans-extension | |
384 | (file-name-nondirectory buffer-file-name)))) | |
72a81656 | 385 | (filename (concat (file-name-as-directory |
4b67ea89 CD |
386 | (or pub-dir |
387 | (org-export-directory :LaTeX ext-plist))) | |
72a81656 | 388 | (file-name-sans-extension |
b349f79f CD |
389 | (or (and subtree-p |
390 | (org-entry-get rbeg "EXPORT_FILE_NAME" t)) | |
391 | (file-name-nondirectory ;sans-extension | |
392 | buffer-file-name))) | |
393 | ".tex")) | |
72a81656 CD |
394 | (filename (if (equal (file-truename filename) |
395 | (file-truename buffer-file-name)) | |
396 | (concat filename ".tex") | |
397 | filename)) | |
398 | (buffer (if to-buffer | |
399 | (cond | |
400 | ((eq to-buffer 'string) (get-buffer-create | |
401 | "*Org LaTeX Export*")) | |
402 | (t (get-buffer-create to-buffer))) | |
403 | (find-file-noselect filename))) | |
72a81656 | 404 | (odd org-odd-levels-only) |
db9c3fb1 | 405 | (header (org-export-latex-make-header title opt-plist)) |
4b67ea89 CD |
406 | (skip (cond (subtree-p nil) |
407 | (region-p t) | |
db9c3fb1 | 408 | ;; never skip first lines when exporting a subtree |
4b67ea89 | 409 | (t (plist-get opt-plist :skip-before-1st-heading)))) |
72a81656 CD |
410 | (text (plist-get opt-plist :text)) |
411 | (first-lines (if skip "" (org-export-latex-first-lines))) | |
412 | (coding-system (and (boundp 'buffer-file-coding-system) | |
413 | buffer-file-coding-system)) | |
414 | (coding-system-for-write (or org-export-latex-coding-system | |
415 | coding-system)) | |
416 | (save-buffer-coding-system (or org-export-latex-coding-system | |
417 | coding-system)) | |
418 | (region (buffer-substring | |
419 | (if region-p (region-beginning) (point-min)) | |
420 | (if region-p (region-end) (point-max)))) | |
421 | (string-for-export | |
20908596 | 422 | (org-export-preprocess-string |
d5098885 | 423 | region :emph-multiline t |
72a81656 | 424 | :for-LaTeX t |
d5098885 | 425 | :comments nil |
15841868 | 426 | :add-text (if (eq to-buffer 'string) nil text) |
d5098885 | 427 | :skip-before-1st-heading skip |
621f83e4 CD |
428 | :select-tags (plist-get opt-plist :select-tags) |
429 | :exclude-tags (plist-get opt-plist :exclude-tags) | |
72a81656 | 430 | :LaTeX-fragments nil))) |
15841868 | 431 | |
db9c3fb1 | 432 | (set-buffer buffer) |
72a81656 | 433 | (erase-buffer) |
0b8568f5 | 434 | |
15841868 JW |
435 | (and (fboundp 'set-buffer-file-coding-system) |
436 | (set-buffer-file-coding-system coding-system-for-write)) | |
437 | ||
db9c3fb1 | 438 | ;; insert the header and initial document commands |
15841868 | 439 | (unless (or (eq to-buffer 'string) body-only) |
db9c3fb1 | 440 | (insert header)) |
15841868 JW |
441 | |
442 | ;; insert text found in #+TEXT | |
443 | (when (and text (not (eq to-buffer 'string))) | |
db9c3fb1 CD |
444 | (insert (org-export-latex-content |
445 | text '(lists tables fixed-width keywords)) | |
446 | "\n\n")) | |
15841868 JW |
447 | |
448 | ;; insert lines before the first headline | |
449 | (unless (or skip (eq to-buffer 'string)) | |
450 | (insert first-lines)) | |
72a81656 CD |
451 | |
452 | ;; handle the case where the region does not begin with a section | |
453 | (when region-p | |
454 | (insert (with-temp-buffer | |
455 | (insert string-for-export) | |
456 | (org-export-latex-first-lines)))) | |
457 | ||
15841868 | 458 | ;; export the content of headlines |
72a81656 CD |
459 | (org-export-latex-global |
460 | (with-temp-buffer | |
461 | (insert string-for-export) | |
462 | (goto-char (point-min)) | |
15841868 JW |
463 | (when (re-search-forward "^\\(\\*+\\) " nil t) |
464 | (let* ((asters (length (match-string 1))) | |
465 | (level (if odd (- asters 2) (- asters 1)))) | |
db9c3fb1 | 466 | (setq org-export-latex-add-level |
15841868 JW |
467 | (if odd (1- (/ (1+ asters) 2)) (1- asters))) |
468 | (org-export-latex-parse-global level odd))))) | |
469 | ||
470 | ;; finalization | |
72a81656 | 471 | (unless body-only (insert "\n\\end{document}")) |
0b8568f5 | 472 | (or to-buffer (save-buffer)) |
72a81656 CD |
473 | (goto-char (point-min)) |
474 | (message "Exporting to LaTeX...done") | |
15841868 JW |
475 | (prog1 |
476 | (if (eq to-buffer 'string) | |
477 | (prog1 (buffer-substring (point-min) (point-max)) | |
478 | (kill-buffer (current-buffer))) | |
479 | (current-buffer)) | |
480 | (set-window-configuration wcf)))) | |
481 | ||
71d35b24 CD |
482 | ;;;###autoload |
483 | (defun org-export-as-pdf (arg &optional hidden ext-plist | |
484 | to-buffer body-only pub-dir) | |
485 | "Export as LaTeX, then process through to PDF." | |
486 | (interactive "P") | |
487 | (message "Exporting to PDF...") | |
488 | (let* ((wconfig (current-window-configuration)) | |
489 | (lbuf (org-export-as-latex arg hidden ext-plist | |
490 | to-buffer body-only pub-dir)) | |
491 | (file (buffer-file-name lbuf)) | |
492 | (base (file-name-sans-extension (buffer-file-name lbuf))) | |
493 | (pdffile (concat base ".pdf"))) | |
494 | (and (file-exists-p pdffile) (delete-file pdffile)) | |
495 | (message "Processing LaTeX file...") | |
496 | (shell-command (format "pdflatex -interaction nonstopmode %s" | |
497 | (shell-quote-argument file))) | |
498 | (shell-command (format "pdflatex -interaction nonstopmode %s" | |
499 | (shell-quote-argument file))) | |
500 | (message "Processing LaTeX file...done") | |
501 | (if (not (file-exists-p pdffile)) | |
502 | (error "PDF file was not produced") | |
503 | (set-window-configuration wconfig) | |
504 | (when org-export-pdf-remove-logfiles | |
505 | (dolist (ext '("aux" "log" "out" "toc")) | |
506 | (setq file (concat base "." ext)) | |
507 | (and (file-exists-p file) (delete-file file)))) | |
508 | (message "Exporting to PDF...done") | |
509 | pdffile))) | |
510 | ||
511 | ;;;###autoload | |
512 | (defun org-export-as-pdf-and-open (arg) | |
513 | "Export as LaTeX, then process through to PDF, and open." | |
514 | (interactive "P") | |
515 | (let ((pdffile (org-export-as-pdf arg))) | |
516 | (if pdffile | |
517 | (org-open-file pdffile) | |
518 | (error "PDF file was not produced")))) | |
519 | ||
0b8568f5 | 520 | ;;; Parsing functions: |
db9c3fb1 | 521 | |
72a81656 CD |
522 | (defun org-export-latex-parse-global (level odd) |
523 | "Parse the current buffer recursively, starting at LEVEL. | |
524 | If ODD is non-nil, assume the buffer only contains odd sections. | |
db9c3fb1 | 525 | Return a list reflecting the document structure." |
72a81656 CD |
526 | (save-excursion |
527 | (goto-char (point-min)) | |
528 | (let* ((cnt 0) output | |
db9c3fb1 | 529 | (depth org-export-latex-sectioning-depth)) |
72a81656 CD |
530 | (while (re-search-forward |
531 | (concat "^\\(\\(?:\\*\\)\\{" | |
532 | (number-to-string (+ (if odd 2 1) level)) | |
533 | "\\}\\) \\(.*\\)$") | |
534 | ;; make sure that there is no upper heading | |
535 | (when (> level 0) | |
536 | (save-excursion | |
537 | (save-match-data | |
538 | (re-search-forward | |
539 | (concat "^\\(\\(?:\\*\\)\\{" | |
540 | (number-to-string level) | |
541 | "\\}\\) \\(.*\\)$") nil t)))) t) | |
542 | (setq cnt (1+ cnt)) | |
543 | (let* ((pos (match-beginning 0)) | |
544 | (heading (match-string 2)) | |
545 | (nlevel (if odd (/ (+ 3 level) 2) (1+ level)))) | |
546 | (save-excursion | |
547 | (narrow-to-region | |
548 | (point) | |
549 | (save-match-data | |
550 | (if (re-search-forward | |
551 | (concat "^\\(\\(?:\\*\\)\\{" | |
552 | (number-to-string (+ (if odd 2 1) level)) | |
553 | "\\}\\) \\(.*\\)$") nil t) | |
554 | (match-beginning 0) | |
555 | (point-max)))) | |
556 | (goto-char (point-min)) | |
557 | (setq output | |
558 | (append output | |
559 | (list | |
560 | (list | |
561 | `(pos . ,pos) | |
562 | `(level . ,nlevel) | |
563 | `(occur . ,cnt) | |
564 | `(heading . ,heading) | |
565 | `(content . ,(org-export-latex-parse-content)) | |
db9c3fb1 | 566 | `(subcontent . ,(org-export-latex-parse-subcontent |
72a81656 CD |
567 | level odd))))))) |
568 | (widen))) | |
569 | (list output)))) | |
570 | ||
571 | (defun org-export-latex-parse-content () | |
572 | "Extract the content of a section." | |
573 | (let ((beg (point)) | |
574 | (end (if (re-search-forward "^\\(\\*\\)+ .*$" nil t) | |
575 | (progn (beginning-of-line) (point)) | |
576 | (point-max)))) | |
577 | (buffer-substring beg end))) | |
578 | ||
579 | (defun org-export-latex-parse-subcontent (level odd) | |
580 | "Extract the subcontent of a section at LEVEL. | |
581 | If ODD Is non-nil, assume subcontent only contains odd sections." | |
582 | (if (not (re-search-forward | |
583 | (concat "^\\(\\(?:\\*\\)\\{" | |
584 | (number-to-string (+ (if odd 4 2) level)) | |
585 | "\\}\\) \\(.*\\)$") | |
586 | nil t)) | |
587 | nil ; subcontent is nil | |
588 | (org-export-latex-parse-global (+ (if odd 2 1) level) odd))) | |
589 | ||
0b8568f5 | 590 | ;;; Rendering functions: |
72a81656 CD |
591 | (defun org-export-latex-global (content) |
592 | "Export CONTENT to LaTeX. | |
593 | CONTENT is an element of the list produced by | |
594 | `org-export-latex-parse-global'." | |
595 | (if (eq (car content) 'subcontent) | |
596 | (mapc 'org-export-latex-sub (cdr content)) | |
597 | (org-export-latex-sub (car content)))) | |
598 | ||
599 | (defun org-export-latex-sub (subcontent) | |
600 | "Export the list SUBCONTENT to LaTeX. | |
601 | SUBCONTENT is an alist containing information about the headline | |
602 | and its content." | |
db9c3fb1 | 603 | (let ((num (plist-get org-export-latex-options-plist :section-numbers))) |
d5098885 | 604 | (mapc (lambda(x) (org-export-latex-subcontent x num)) subcontent))) |
72a81656 | 605 | |
d5098885 | 606 | (defun org-export-latex-subcontent (subcontent num) |
621f83e4 CD |
607 | "Export each cell of SUBCONTENT to LaTeX. |
608 | If NUM, export sections as numerical sections." | |
609 | (let* ((heading (org-export-latex-fontify-headline | |
610 | (cdr (assoc 'heading subcontent)))) | |
611 | (level (- (cdr (assoc 'level subcontent)) | |
612 | org-export-latex-add-level)) | |
613 | (occur (number-to-string (cdr (assoc 'occur subcontent)))) | |
614 | (content (cdr (assoc 'content subcontent))) | |
615 | (subcontent (cadr (assoc 'subcontent subcontent))) | |
ce4fdcb9 CD |
616 | (label (org-get-text-property-any 0 'target heading)) |
617 | (label-list (cons label (cdr (assoc label | |
618 | org-export-target-aliases))))) | |
db9c3fb1 | 619 | (cond |
72a81656 | 620 | ;; Normal conversion |
db9c3fb1 | 621 | ((<= level org-export-latex-sectioning-depth) |
71d35b24 CD |
622 | (let* ((sec (nth (1- level) org-export-latex-sectioning)) |
623 | start end) | |
624 | (if (consp (cdr sec)) | |
625 | (setq start (nth (if num 0 2) sec) | |
626 | end (nth (if num 1 3) sec)) | |
627 | (setq start (if num (car sec) (cdr sec)))) | |
628 | (insert (format start heading) "\n") | |
ce4fdcb9 CD |
629 | (when label |
630 | (insert (mapconcat (lambda (l) (format "\\label{%s}" l)) | |
631 | label-list "\n") "\n")) | |
71d35b24 CD |
632 | (insert (org-export-latex-content content)) |
633 | (cond ((stringp subcontent) (insert subcontent)) | |
634 | ((listp subcontent) (org-export-latex-sub subcontent))) | |
635 | (if end (insert end "\n")))) | |
72a81656 | 636 | ;; At a level under the hl option: we can drop this subsection |
db9c3fb1 | 637 | ((> level org-export-latex-sectioning-depth) |
72a81656 | 638 | (cond ((eq org-export-latex-low-levels 'description) |
621f83e4 CD |
639 | (insert (format "\\begin{description}\n\n\\item[%s]%s\n\n" |
640 | heading | |
641 | (if label (format "\\label{%s}" label) ""))) | |
72a81656 CD |
642 | (insert (org-export-latex-content content)) |
643 | (cond ((stringp subcontent) (insert subcontent)) | |
644 | ((listp subcontent) (org-export-latex-sub subcontent))) | |
645 | (insert "\\end{description}\n")) | |
646 | ((stringp org-export-latex-low-levels) | |
647 | (insert (format org-export-latex-low-levels heading) "\n") | |
621f83e4 | 648 | (when label (insert (format "\\label{%s}\n" label))) |
72a81656 CD |
649 | (insert (org-export-latex-content content)) |
650 | (cond ((stringp subcontent) (insert subcontent)) | |
651 | ((listp subcontent) (org-export-latex-sub subcontent))))))))) | |
652 | ||
0b8568f5 | 653 | ;;; Exporting internals: |
db9c3fb1 | 654 | (defun org-export-latex-set-initial-vars (ext-plist level) |
0b8568f5 | 655 | "Store org local variables required for LaTeX export. |
db9c3fb1 CD |
656 | EXT-PLIST is an optional additional plist. |
657 | LEVEL indicates the default depth for export." | |
658 | (setq org-export-latex-todo-keywords-1 org-todo-keywords-1 | |
659 | org-export-latex-all-targets-re | |
0b8568f5 | 660 | (org-make-target-link-regexp (org-all-targets)) |
db9c3fb1 | 661 | org-export-latex-options-plist |
0b8568f5 JW |
662 | (org-combine-plists (org-default-export-plist) ext-plist |
663 | (org-infile-export-plist)) | |
db9c3fb1 CD |
664 | org-export-latex-class |
665 | (save-excursion | |
666 | (goto-char (point-min)) | |
667 | (if (and (re-search-forward "^#\\+LaTeX_CLASS:[ \t]*\\([a-zA-Z]+\\)" nil t) | |
668 | (assoc (match-string 1) org-export-latex-classes)) | |
669 | (match-string 1) | |
670 | org-export-latex-default-class)) | |
671 | org-export-latex-header | |
672 | (cadr (assoc org-export-latex-class org-export-latex-classes)) | |
673 | org-export-latex-sectioning | |
674 | (cddr (assoc org-export-latex-class org-export-latex-classes)) | |
675 | org-export-latex-sectioning-depth | |
676 | (or level | |
677 | (let ((hl-levels | |
678 | (plist-get org-export-latex-options-plist :headline-levels)) | |
679 | (sec-depth (length org-export-latex-sectioning))) | |
680 | (if (> hl-levels sec-depth) sec-depth hl-levels))))) | |
681 | ||
682 | (defun org-export-latex-make-header (title opt-plist) | |
683 | "Make the LaTeX header and return it as a string. | |
684 | TITLE is the current title from the buffer or region. | |
685 | OPT-PLIST is the options plist for current buffer." | |
686 | (let ((toc (plist-get opt-plist :table-of-contents)) | |
687 | (author (plist-get opt-plist :author))) | |
688 | (concat | |
15841868 JW |
689 | (if (plist-get opt-plist :time-stamp-file) |
690 | (format-time-string "% Created %Y-%m-%d %a %H:%M\n")) | |
db9c3fb1 CD |
691 | ;; insert LaTeX custom header |
692 | org-export-latex-header | |
693 | "\n" | |
15841868 JW |
694 | ;; insert information on LaTeX packages |
695 | (when org-export-latex-packages-alist | |
696 | (mapconcat (lambda(p) | |
697 | (if (equal "" (car p)) | |
698 | (format "\\usepackage{%s}" (cadr p)) | |
699 | (format "\\usepackage[%s]{%s}" | |
700 | (car p) (cadr p)))) | |
701 | org-export-latex-packages-alist "\n")) | |
db9c3fb1 | 702 | ;; insert additional commands in the header |
621f83e4 | 703 | (plist-get opt-plist :latex-header-extra) |
db9c3fb1 | 704 | org-export-latex-append-header |
15841868 | 705 | ;; insert the title |
db9c3fb1 CD |
706 | (format |
707 | "\n\n\\title{%s}\n" | |
03f3cf35 JW |
708 | ;; convert the title |
709 | (org-export-latex-content | |
db9c3fb1 | 710 | title '(lists tables fixed-width keywords))) |
15841868 JW |
711 | ;; insert author info |
712 | (if (plist-get opt-plist :author-info) | |
db9c3fb1 CD |
713 | (format "\\author{%s}\n" |
714 | (or author user-full-name)) | |
15841868 | 715 | (format "%%\\author{%s}\n" |
db9c3fb1 | 716 | (or author user-full-name))) |
15841868 JW |
717 | ;; insert the date |
718 | (format "\\date{%s}\n" | |
db9c3fb1 | 719 | (format-time-string |
15841868 JW |
720 | (or (plist-get opt-plist :date) |
721 | org-export-latex-date-format))) | |
15841868 JW |
722 | ;; beginning of the document |
723 | "\n\\begin{document}\n\n" | |
15841868 JW |
724 | ;; insert the title command |
725 | (if (string-match "%s" org-export-latex-title-command) | |
db9c3fb1 | 726 | (format org-export-latex-title-command title) |
15841868 JW |
727 | org-export-latex-title-command) |
728 | "\n\n" | |
15841868 | 729 | ;; table of contents |
db9c3fb1 | 730 | (when (and org-export-with-toc |
15841868 JW |
731 | (plist-get opt-plist :section-numbers)) |
732 | (cond ((numberp toc) | |
733 | (format "\\setcounter{tocdepth}{%s}\n\\tableofcontents\n\n" | |
734 | (min toc (plist-get opt-plist :headline-levels)))) | |
735 | (toc (format "\\setcounter{tocdepth}{%s}\n\\tableofcontents\n\n" | |
736 | (plist-get opt-plist :headline-levels)))))))) | |
0b8568f5 JW |
737 | |
738 | (defun org-export-latex-first-lines (&optional comments) | |
739 | "Export the first lines before first headline. | |
740 | COMMENTS is either nil to replace them with the empty string or a | |
741 | formatting string like %%%%s if we want to comment them out." | |
742 | (save-excursion | |
743 | (goto-char (point-min)) | |
db9c3fb1 | 744 | (if (org-at-heading-p) (beginning-of-line 2)) |
03f3cf35 | 745 | (let* ((pt (point)) |
db9c3fb1 | 746 | (end (if (and (re-search-forward "^\\* " nil t) |
03f3cf35 | 747 | (not (eq pt (match-beginning 0)))) |
0b8568f5 JW |
748 | (goto-char (match-beginning 0)) |
749 | (goto-char (point-max))))) | |
750 | (org-export-latex-content | |
20908596 | 751 | (org-export-preprocess-string |
0b8568f5 | 752 | (buffer-substring (point-min) end) |
0b8568f5 | 753 | :for-LaTeX t |
d5098885 JW |
754 | :emph-multiline t |
755 | :add-text nil | |
0b8568f5 JW |
756 | :comments nil |
757 | :skip-before-1st-heading nil | |
758 | :LaTeX-fragments nil))))) | |
759 | ||
db9c3fb1 CD |
760 | (defun org-export-latex-content (content &optional exclude-list) |
761 | "Convert CONTENT string to LaTeX. | |
762 | Don't perform conversions that are in EXCLUDE-LIST. Recognized | |
763 | conversion types are: quotation-marks, emphasis, sub-superscript, | |
764 | links, keywords, lists, tables, fixed-width" | |
765 | (with-temp-buffer | |
766 | (insert content) | |
767 | (unless (memq 'quotation-marks exclude-list) | |
768 | (org-export-latex-quotation-marks)) | |
769 | (unless (memq 'emphasis exclude-list) | |
770 | (when (plist-get org-export-latex-options-plist :emphasize) | |
771 | (org-export-latex-fontify))) | |
772 | (unless (memq 'sub-superscript exclude-list) | |
773 | (org-export-latex-special-chars | |
774 | (plist-get org-export-latex-options-plist :sub-superscript))) | |
775 | (unless (memq 'links exclude-list) | |
776 | (org-export-latex-links)) | |
777 | (unless (memq 'keywords exclude-list) | |
778 | (org-export-latex-keywords | |
779 | (plist-get org-export-latex-options-plist :timestamps))) | |
780 | (unless (memq 'lists exclude-list) | |
781 | (org-export-latex-lists)) | |
782 | (unless (memq 'tables exclude-list) | |
783 | (org-export-latex-tables | |
784 | (plist-get org-export-latex-options-plist :tables))) | |
785 | (unless (memq 'fixed-width exclude-list) | |
786 | (org-export-latex-fixed-width | |
787 | (plist-get org-export-latex-options-plist :fixed-width))) | |
788 | ;; return string | |
789 | (buffer-substring (point-min) (point-max)))) | |
790 | ||
791 | (defun org-export-latex-protect-string (s) | |
621f83e4 | 792 | "Add the org-protected property to string S." |
db9c3fb1 CD |
793 | (add-text-properties 0 (length s) '(org-protected t) s) s) |
794 | ||
795 | (defun org-export-latex-protect-char-in-string (char-list string) | |
796 | "Add org-protected text-property to char from CHAR-LIST in STRING." | |
797 | (with-temp-buffer | |
798 | (save-match-data | |
799 | (insert string) | |
800 | (goto-char (point-min)) | |
801 | (while (re-search-forward (regexp-opt char-list) nil t) | |
802 | (add-text-properties (match-beginning 0) | |
803 | (match-end 0) '(org-protected t))) | |
804 | (buffer-string)))) | |
805 | ||
0b8568f5 | 806 | (defun org-export-latex-keywords-maybe (remove-list) |
72a81656 CD |
807 | "Maybe remove keywords depending on rules in REMOVE-LIST." |
808 | (goto-char (point-min)) | |
db9c3fb1 CD |
809 | (let ((re-todo (mapconcat 'identity org-export-latex-todo-keywords-1 "\\|")) |
810 | (case-fold-search nil)) | |
72a81656 CD |
811 | ;; convert TODO keywords |
812 | (when (re-search-forward (concat "^\\(" re-todo "\\)") nil t) | |
813 | (if (plist-get remove-list :todo) | |
814 | (replace-match "") | |
815 | (replace-match (format "\\texttt{%s}" (match-string 1)) t t))) | |
816 | ;; convert priority string | |
817 | (when (re-search-forward "\\[\\\\#.\\]" nil t) | |
818 | (if (plist-get remove-list :priority) | |
819 | (replace-match "") | |
820 | (replace-match (format "\\texttt{%s}" (match-string 0)) t t))) | |
821 | ;; convert tags | |
2c3ad40d | 822 | (when (re-search-forward "\\(:[a-zA-Z0-9_@]+\\)+:" nil t) |
0b8568f5 JW |
823 | (if (or (not org-export-with-tags) |
824 | (plist-get remove-list :tags)) | |
72a81656 | 825 | (replace-match "") |
621f83e4 | 826 | (replace-match |
2c3ad40d | 827 | (org-export-latex-protect-string |
621f83e4 CD |
828 | (format "\\texttt{%s}" |
829 | (save-match-data | |
830 | (replace-regexp-in-string | |
831 | "_" "\\\\_" (match-string 0))))) | |
832 | t t))))) | |
72a81656 | 833 | |
db9c3fb1 | 834 | (defun org-export-latex-fontify-headline (string) |
621f83e4 | 835 | "Fontify special words in STRING." |
72a81656 CD |
836 | (with-temp-buffer |
837 | ;; FIXME: org-inside-LaTeX-fragment-p doesn't work when the $...$ is at | |
838 | ;; the beginning of the buffer - inserting "\n" is safe here though. | |
db9c3fb1 | 839 | (insert "\n" string) |
72a81656 | 840 | (goto-char (point-min)) |
db9c3fb1 | 841 | (when (plist-get org-export-latex-options-plist :emphasize) |
0b8568f5 JW |
842 | (org-export-latex-fontify)) |
843 | (org-export-latex-keywords-maybe | |
d5098885 | 844 | org-export-latex-remove-from-headlines) |
2c3ad40d CD |
845 | (org-export-latex-special-chars |
846 | (plist-get org-export-latex-options-plist :sub-superscript)) | |
72a81656 | 847 | (org-export-latex-links) |
621f83e4 CD |
848 | ; (org-trim (buffer-substring-no-properties (point-min) (point-max))))) |
849 | (org-trim (buffer-string)))) | |
72a81656 | 850 | |
72a81656 | 851 | (defun org-export-latex-quotation-marks () |
621f83e4 | 852 | "Export quotation marks depending on language conventions." |
db9c3fb1 | 853 | (let* ((lang (plist-get org-export-latex-options-plist :language)) |
72a81656 | 854 | (quote-rpl (if (equal lang "fr") |
621f83e4 CD |
855 |