org-export-latex.el 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. ;;; org-export-latex.el --- LaTeX exporter for Org-mode
  2. ;; Copyright (C) 2007 Free Software Foundation, Inc.
  3. ;;
  4. ;; Author: Bastien Guerry <bzg AT altern DOT org>
  5. ;; Maintainer: Bastien Guerry <bzg AT altern DOT org>
  6. ;; Version: $Id: org-export-latex.el,v 0.26b 2007/08/21 14:46:58 guerry Exp guerry $
  7. ;; Keywords: org organizer latex export convert
  8. ;; X-URL: <http://www.cognition.ens.fr/~guerry/u/org-export-latex.el>
  9. ;;
  10. ;; This file is part of GNU Emacs.
  11. ;;
  12. ;; This program is free software; you can redistribute it and/or modify
  13. ;; it under the terms of the GNU General Public License as published by
  14. ;; the Free Software Foundation; either version 2, or (at your option)
  15. ;; any later version.
  16. ;;
  17. ;; This program is distributed in the hope that it will be useful,
  18. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ;; GNU General Public License for more details.
  21. ;;
  22. ;; You should have received a copy of the GNU General Public License
  23. ;; along with this program; if not, write to the Free Software
  24. ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. ;;; Commentary:
  26. ;; This library is a LaTeX exporter for org-mode.
  27. ;;
  28. ;; Put this file into your load-path and the following into your ~/.emacs:
  29. ;; (require 'org-export-latex)
  30. ;;
  31. ;; The interactive functions are similar to those of the HTML exporter:
  32. ;;
  33. ;; M-x `org-export-as-latex'
  34. ;; M-x `org-export-as-latex-batch'
  35. ;; M-x `org-export-as-latex-to-buffer'
  36. ;; M-x `org-export-region-as-latex'
  37. ;; M-x `org-replace-region-by-latex'
  38. ;;; History:
  39. ;;
  40. ;; I started this piece of code in may 2007. Special thanks to Carsten
  41. ;; Dominik for helping me on this.
  42. ;;
  43. ;;; Code:
  44. (require 'org)
  45. (require 'footnote)
  46. (defvar org-latex-options-plist nil)
  47. (defvar org-latex-todo-keywords-1 nil)
  48. (defvar org-latex-all-targets-regexp nil)
  49. (defvar org-latex-add-level 0)
  50. (defvar org-latex-sectioning-depth 0)
  51. (defvar org-latex-special-string-regexps
  52. '(org-ts-regexp
  53. org-scheduled-string
  54. org-deadline-string
  55. org-clock-string)
  56. "A list of regexps to convert as special keywords.")
  57. (defcustom org-export-latex-sectioning-alist
  58. '((1 "\\section{%s}" "\\section*{%s}")
  59. (2 "\\subsection{%s}" "\\subsection*{%s}")
  60. (3 "\\subsubsection{%s}" "\\subsubsection*{%s}")
  61. (4 "\\paragraph{%s}" "\\paragraph*{%s}")
  62. (5 "\\subparagraph{%s}" "\\subparagraph*{%s}"))
  63. "Alist of LaTeX commands for inserting sections.
  64. Here is the structure of each cell:
  65. \(level unnumbered-section numbered-section\)
  66. The %s formatter will be replaced by the title of the section."
  67. :group 'org-export-latex
  68. :type 'alist)
  69. (defcustom org-export-latex-emphasis-alist
  70. '(("*" "\\textbf{%s}")
  71. ("/" "\\emph{%s}")
  72. ("_" "\\underline{%s}")
  73. ("+" "\\texttt{%s}")
  74. ("=" "\\texttt{%s}"))
  75. "Alist of LaTeX expressions to convert emphasis fontifiers."
  76. :group 'org-export-latex
  77. :type 'alist)
  78. (defcustom org-export-latex-preamble
  79. "\\documentclass[11pt,a4paper]{article}
  80. \\usepackage[utf8]{inputenc}
  81. \\usepackage[T1]{fontenc}
  82. \\usepackage{hyperref}"
  83. "Preamble to be inserted at the very beginning of the LaTeX export."
  84. :group 'org-export-latex
  85. :type 'string)
  86. (defcustom org-export-latex-date-format nil
  87. "Format string for \\date{...}."
  88. :group 'org-export-latex
  89. :type 'string)
  90. (defcustom org-export-latex-packages-alist nil
  91. "Alist of packages to be inserted in the preamble.
  92. Each cell is of the forma \( option . package \).
  93. For example:
  94. \(setq org-export-latex-packages-alist
  95. '((\"french\" \"babel\"))"
  96. :group 'org-export-latex
  97. :type 'alist)
  98. (defcustom org-export-latex-low-levels 'description
  99. "Choice for converting sections that are below the current
  100. admitted level of sectioning. This can be either nil (ignore the
  101. sections), 'description (convert them as description lists) or a
  102. string to be used instead of \\section{%s} (a %s for inserted the
  103. headline is mandatory)."
  104. :group 'org-export-latex
  105. :type '(choice (const :tag "Ignore" nil)
  106. (symbol :tag "Convert as descriptive list" description)
  107. (string :tag "Use a section string" :value "\\subparagraph{%s}")))
  108. (defcustom org-export-latex-remove-from-headines
  109. '(:todo t :priority t :tags t)
  110. "A plist of keywords to remove from headlines.
  111. Non-nil means remove this keyword type from the headline.
  112. Don't remove the keys, just change their values."
  113. :type 'plist
  114. :group 'org-export-latex)
  115. (defcustom org-export-latex-quotation-marks-convention "en"
  116. "Convention for conversion of the quotation marks.
  117. This value is overriden by any infile language setup."
  118. :group 'org-export-latex
  119. :type '(choice (string :tag "english" "en")
  120. (string :tag "french" "fr")))
  121. (defcustom org-export-latex-image-default-option "width=10em"
  122. "Default option for images."
  123. :group 'org-export-latex
  124. :type '(string))
  125. (defcustom org-export-latex-coding-system nil
  126. "Coding system for the exported LaTex file."
  127. :group 'org-export-latex
  128. :type 'coding-system)
  129. ;; FIXME Do we want this one?
  130. ;; (defun org-export-as-latex-and-open (arg) ...)
  131. ;;;###autoload
  132. (defun org-export-as-latex-batch ()
  133. "Call `org-export-as-latex', may be used in batch processing as
  134. emacs --batch
  135. --load=$HOME/lib/emacs/org.el
  136. --eval \"(setq org-export-headline-levels 2)\"
  137. --visit=MyFile --funcall org-export-as-latex-batch"
  138. (org-export-as-latex org-export-headline-levels 'hidden))
  139. ;;;###autoload
  140. (defun org-export-as-latex-to-buffer (arg)
  141. "Call `org-exort-as-latex` with output to a temporary buffer.
  142. No file is created. The prefix ARG is passed through to `org-export-as-latex'."
  143. (interactive "P")
  144. (org-export-as-latex arg nil nil "*Org LaTeX Export*")
  145. (switch-to-buffer-other-window "*Org LaTeX Export*"))
  146. ;;;###autoload
  147. (defun org-replace-region-by-latex (beg end)
  148. "Replace the region from BEG to END with its LaTeX export.
  149. It assumes the region has `org-mode' syntax, and then convert it to
  150. LaTeX. This can be used in any buffer. For example, you could
  151. write an itemized list in `org-mode' syntax in an LaTeX buffer and
  152. then use this command to convert it."
  153. (interactive "r")
  154. (let (reg latex buf)
  155. (save-window-excursion
  156. (if (org-mode-p)
  157. (setq latex (org-export-region-as-latex
  158. beg end t 'string))
  159. (setq reg (buffer-substring beg end)
  160. buf (get-buffer-create "*Org tmp*"))
  161. (save-excursion
  162. (set-buffer buf)
  163. (erase-buffer)
  164. (insert reg)
  165. (org-mode)
  166. (setq latex (org-export-region-as-latex
  167. (point-min) (point-max) t 'string)))
  168. (kill-buffer buf)))
  169. (delete-region beg end)
  170. (insert latex)))
  171. ;;;###autoload
  172. (defun org-export-region-as-latex (beg end &optional body-only buffer)
  173. "Convert region from BEG to END in `org-mode' buffer to LaTeX.
  174. If prefix arg BODY-ONLY is set, omit file header, footer, and table of
  175. contents, and only produce the region of converted text, useful for
  176. cut-and-paste operations.
  177. If BUFFER is a buffer or a string, use/create that buffer as a target
  178. of the converted LaTeX. If BUFFER is the symbol `string', return the
  179. produced LaTeX as a string and leave not buffer behind. For example,
  180. a Lisp program could call this function in the following way:
  181. (setq latex (org-export-region-as-latex beg end t 'string))
  182. When called interactively, the output buffer is selected, and shown
  183. in a window. A non-interactive call will only retunr the buffer."
  184. (interactive "r\nP")
  185. (when (interactive-p)
  186. (setq buffer "*Org LaTeX Export*"))
  187. (let ((transient-mark-mode t) (zmacs-regions t)
  188. rtn)
  189. (goto-char end)
  190. (set-mark (point)) ;; to activate the region
  191. (goto-char beg)
  192. (setq rtn (org-export-as-latex
  193. nil nil nil
  194. buffer body-only))
  195. (if (fboundp 'deactivate-mark) (deactivate-mark))
  196. (if (and (interactive-p) (bufferp rtn))
  197. (switch-to-buffer-other-window rtn)
  198. rtn)))
  199. ;;;###autoload
  200. (defun org-export-as-latex (arg &optional hidden ext-plist
  201. to-buffer body-only)
  202. "Export current buffer to a LaTeX file."
  203. (interactive "P")
  204. ;; Make sure we have a file name when we need it.
  205. (when (and (not (or to-buffer body-only))
  206. (not buffer-file-name))
  207. (if (buffer-base-buffer)
  208. (org-set-local 'buffer-file-name
  209. (with-current-buffer (buffer-base-buffer)
  210. buffer-file-name))
  211. (error "Need a file name to be able to export")))
  212. (message "Exporting to LaTeX...")
  213. (org-update-radio-target-regexp)
  214. (org-export-latex-set-initial-vars ext-plist)
  215. (let* ((opt-plist org-latex-options-plist)
  216. (filename (concat (file-name-as-directory
  217. (org-export-directory :LaTeX ext-plist))
  218. (file-name-sans-extension
  219. (file-name-nondirectory ;sans-extension
  220. buffer-file-name)) ".tex"))
  221. (filename (if (equal (file-truename filename)
  222. (file-truename buffer-file-name))
  223. (concat filename ".tex")
  224. filename))
  225. (buffer (if to-buffer
  226. (cond
  227. ((eq to-buffer 'string) (get-buffer-create
  228. "*Org LaTeX Export*"))
  229. (t (get-buffer-create to-buffer)))
  230. (find-file-noselect filename)))
  231. (region-p (org-region-active-p))
  232. (odd org-odd-levels-only)
  233. (preamble (org-export-latex-make-preamble opt-plist))
  234. (skip (plist-get opt-plist :skip-before-1st-heading))
  235. (text (plist-get opt-plist :text))
  236. (first-lines (if skip "" (org-export-latex-first-lines)))
  237. (coding-system (and (boundp 'buffer-file-coding-system)
  238. buffer-file-coding-system))
  239. (coding-system-for-write (or org-export-latex-coding-system
  240. coding-system))
  241. (save-buffer-coding-system (or org-export-latex-coding-system
  242. coding-system))
  243. (region (buffer-substring
  244. (if region-p (region-beginning) (point-min))
  245. (if region-p (region-end) (point-max))))
  246. (string-for-export
  247. ;; FIXME Use org-cleaned-string-for-export instead, only when
  248. ;; everyone uses Org >5.04
  249. (org-latex-cleaned-string-for-export
  250. region :for-html nil
  251. :comments nil
  252. :for-LaTeX t
  253. :skip-before-1st-heading nil
  254. :LaTeX-fragments nil)))
  255. (set-buffer buffer)
  256. (erase-buffer)
  257. (unless body-only (insert preamble))
  258. (when text (insert (org-export-latex-content text) "\n\n"))
  259. (unless skip (insert first-lines))
  260. ;; handle the case where the region does not begin with a section
  261. (when region-p
  262. (insert (with-temp-buffer
  263. (insert string-for-export)
  264. (org-export-latex-first-lines))))
  265. (org-export-latex-global
  266. (with-temp-buffer
  267. (insert string-for-export)
  268. (goto-char (point-min))
  269. (re-search-forward "^\\(\\*+\\) " nil t)
  270. (let* ((asters (length (match-string 1)))
  271. (level (if odd (- asters 2) (- asters 1))))
  272. (setq org-latex-add-level
  273. (if odd (1- (/ (1+ asters) 2)) (1- asters)))
  274. (org-export-latex-parse-global level odd))))
  275. (unless body-only (insert "\n\\end{document}"))
  276. (or to-buffer (write-file filename))
  277. (goto-char (point-min))
  278. (message "Exporting to LaTeX...done")
  279. (if (eq to-buffer 'string)
  280. (prog1 (buffer-substring (point-min) (point-max))
  281. (kill-buffer (current-buffer)))
  282. (current-buffer))))
  283. (defun org-export-latex-set-initial-vars (ext-plist)
  284. "Store org local variables required for LaTeX export.
  285. EXT-PLIST is an optional additional plist."
  286. (setq org-latex-todo-keywords-1 org-todo-keywords-1
  287. org-latex-all-targets-regexp
  288. (org-make-target-link-regexp (org-all-targets))
  289. org-latex-options-plist
  290. (org-combine-plists (org-default-export-plist) ext-plist
  291. (org-infile-export-plist))
  292. org-latex-sectioning-depth
  293. (let ((hl-levels (plist-get org-latex-options-plist :headline-levels))
  294. (sec-depth (length org-export-latex-sectioning-alist)))
  295. ;; Fall back on org-export-latex-sectioning-alist length if
  296. ;; headline-levels goes beyond it
  297. (if (> hl-levels sec-depth) sec-depth hl-levels))))
  298. (defun org-export-latex-make-preamble (opt-plist)
  299. "Make the LaTeX preamble and return it as a string.
  300. Argument OPT-PLIST is the options plist for current buffer."
  301. (let ((toc (plist-get opt-plist :table-of-contents)))
  302. (format (concat org-export-latex-preamble
  303. "
  304. %s
  305. \\begin{document}
  306. \\title{%s}
  307. %s
  308. %s
  309. \\maketitle
  310. %s
  311. %s
  312. ")
  313. (if org-export-latex-packages-alist
  314. (mapconcat (lambda(p)
  315. (if (equal "" (car p))
  316. (format "\\usepackage{%s}" (cadr p))
  317. (format "\\usepackage[%s]{%s}"
  318. (car p) (cadr p))))
  319. org-export-latex-packages-alist "\n") "")
  320. (or (plist-get opt-plist :title)
  321. (and (not
  322. (plist-get opt-plist :skip-before-1st-heading))
  323. (org-export-grab-title-from-buffer))
  324. (and buffer-file-name
  325. (file-name-sans-extension
  326. (file-name-nondirectory buffer-file-name)))
  327. "UNTITLED")
  328. (if (plist-get opt-plist :author-info)
  329. (format "\\author{%s}"
  330. (or (plist-get opt-plist :author) user-full-name))
  331. (format "%%\\author{%s}"
  332. (or (plist-get opt-plist :author) user-full-name)))
  333. (if (plist-get opt-plist :timestamps)
  334. (format "\\date{%s}"
  335. (format-time-string (or org-export-latex-date-format
  336. (car org-time-stamp-formats))))
  337. "%\\date{}")
  338. (if (and (plist-get opt-plist :section-numbers) toc)
  339. (format "\\setcounter{tocdepth}{%s}"
  340. (plist-get opt-plist :headline-levels)) "")
  341. (if (and (plist-get opt-plist :section-numbers) toc)
  342. "\\tableofcontents" ""))))
  343. (defun org-export-latex-first-lines (&optional comments)
  344. "Export the first lines before first headline.
  345. COMMENTS is either nil to replace them with the empty string or a
  346. formatting string like %%%%s if we want to comment them out."
  347. (save-excursion
  348. (goto-char (point-min))
  349. (let* ((end (if (re-search-forward "^\\*" nil t)
  350. (goto-char (match-beginning 0))
  351. (goto-char (point-max)))))
  352. (org-export-latex-content
  353. (org-latex-cleaned-string-for-export
  354. (buffer-substring (point-min) end)
  355. :for-html nil
  356. :for-LaTeX t
  357. :comments nil
  358. :skip-before-1st-heading nil
  359. :LaTeX-fragments nil)))))
  360. (defun org-export-latex-parse-global (level odd)
  361. "Parse the current buffer recursively, starting at LEVEL.
  362. If ODD is non-nil, assume the buffer only contains odd sections.
  363. Return A list reflecting the document structure."
  364. (save-excursion
  365. (goto-char (point-min))
  366. (let* ((cnt 0) output
  367. (depth org-latex-sectioning-depth))
  368. (while (re-search-forward
  369. (concat "^\\(\\(?:\\*\\)\\{"
  370. (number-to-string (+ (if odd 2 1) level))
  371. "\\}\\) \\(.*\\)$")
  372. ;; make sure that there is no upper heading
  373. (when (> level 0)
  374. (save-excursion
  375. (save-match-data
  376. (re-search-forward
  377. (concat "^\\(\\(?:\\*\\)\\{"
  378. (number-to-string level)
  379. "\\}\\) \\(.*\\)$") nil t)))) t)
  380. (setq cnt (1+ cnt))
  381. (let* ((pos (match-beginning 0))
  382. (heading (match-string 2))
  383. (nlevel (if odd (/ (+ 3 level) 2) (1+ level))))
  384. (save-excursion
  385. (narrow-to-region
  386. (point)
  387. (save-match-data
  388. (if (re-search-forward
  389. (concat "^\\(\\(?:\\*\\)\\{"
  390. (number-to-string (+ (if odd 2 1) level))
  391. "\\}\\) \\(.*\\)$") nil t)
  392. (match-beginning 0)
  393. (point-max))))
  394. (goto-char (point-min))
  395. (setq output
  396. (append output
  397. (list
  398. (list
  399. `(pos . ,pos)
  400. `(level . ,nlevel)
  401. `(occur . ,cnt)
  402. `(heading . ,heading)
  403. `(content . ,(org-export-latex-parse-content))
  404. `(subcontent . ,(org-export-latex-parse-subcontent
  405. level odd)))))))
  406. (widen)))
  407. (list output))))
  408. (defun org-export-latex-parse-content ()
  409. "Extract the content of a section."
  410. (let ((beg (point))
  411. (end (if (re-search-forward "^\\(\\*\\)+ .*$" nil t)
  412. (progn (beginning-of-line) (point))
  413. (point-max))))
  414. (buffer-substring beg end)))
  415. (defun org-export-latex-parse-subcontent (level odd)
  416. "Extract the subcontent of a section at LEVEL.
  417. If ODD Is non-nil, assume subcontent only contains odd sections."
  418. (if (not (re-search-forward
  419. (concat "^\\(\\(?:\\*\\)\\{"
  420. (number-to-string (+ (if odd 4 2) level))
  421. "\\}\\) \\(.*\\)$")
  422. nil t))
  423. nil ; subcontent is nil
  424. (org-export-latex-parse-global (+ (if odd 2 1) level) odd)))
  425. (defun org-export-latex-global (content)
  426. "Export CONTENT to LaTeX.
  427. CONTENT is an element of the list produced by
  428. `org-export-latex-parse-global'."
  429. (if (eq (car content) 'subcontent)
  430. (mapc 'org-export-latex-sub (cdr content))
  431. (org-export-latex-sub (car content))))
  432. (defun org-export-latex-sub (subcontent)
  433. "Export the list SUBCONTENT to LaTeX.
  434. SUBCONTENT is an alist containing information about the headline
  435. and its content."
  436. (mapc (lambda(x) (org-export-latex-subcontent x)) subcontent))
  437. (defun org-export-latex-subcontent (subcontent)
  438. "Export each cell of SUBCONTENT to LaTeX."
  439. (let ((heading (org-export-latex-fontify-headline
  440. (cdr (assoc 'heading subcontent))))
  441. (level (- (cdr (assoc 'level subcontent))
  442. org-latex-add-level))
  443. (occur (number-to-string (cdr (assoc 'occur subcontent))))
  444. (content (cdr (assoc 'content subcontent)))
  445. (subcontent (cadr (assoc 'subcontent subcontent)))
  446. (num (plist-get org-latex-options-plist :section-numbers)))
  447. (cond
  448. ;; Normal conversion
  449. ((<= level org-latex-sectioning-depth)
  450. (let ((sec (assoc level org-export-latex-sectioning-alist)))
  451. (insert (format (if num (cadr sec) (caddr sec)) heading) "\n"))
  452. (insert (org-export-latex-content content))
  453. (cond ((stringp subcontent) (insert subcontent))
  454. ((listp subcontent) (org-export-latex-sub subcontent))))
  455. ;; At a level under the hl option: we can drop this subsection
  456. ((> level org-latex-sectioning-depth)
  457. (cond ((eq org-export-latex-low-levels 'description)
  458. (insert (format "\\begin{description}\n\n\\item[%s]\n\n" heading))
  459. (insert (org-export-latex-content content))
  460. (cond ((stringp subcontent) (insert subcontent))
  461. ((listp subcontent) (org-export-latex-sub subcontent)))
  462. (insert "\\end{description}\n"))
  463. ((stringp org-export-latex-low-levels)
  464. (insert (format org-export-latex-low-levels heading) "\n")
  465. (insert (org-export-latex-content content))
  466. (cond ((stringp subcontent) (insert subcontent))
  467. ((listp subcontent) (org-export-latex-sub subcontent)))))))))
  468. (defun org-export-latex-special-keywords-maybe (remove-list)
  469. "Maybe remove keywords depending on rules in REMOVE-LIST."
  470. (goto-char (point-min))
  471. (let ((re-todo (mapconcat 'identity org-latex-todo-keywords-1 "\\|")))
  472. ;; convert TODO keywords
  473. (when (re-search-forward (concat "^\\(" re-todo "\\)") nil t)
  474. (if (plist-get remove-list :todo)
  475. (replace-match "")
  476. (replace-match (format "\\texttt{%s}" (match-string 1)) t t)))
  477. ;; convert priority string
  478. (when (re-search-forward "\\[\\\\#.\\]" nil t)
  479. (if (plist-get remove-list :priority)
  480. (replace-match "")
  481. (replace-match (format "\\texttt{%s}" (match-string 0)) t t)))
  482. ;; convert tags
  483. (when (re-search-forward "\\(:[a-zA-Z0-9]+\\)+:" nil t)
  484. (if (plist-get remove-list :tags)
  485. (replace-match "")
  486. (replace-match (format "\\texttt{%s}" (match-string 0)) t t)))))
  487. (defun org-export-latex-fontify-headline (headline)
  488. "Fontify special words in a HEADLINE."
  489. (with-temp-buffer
  490. ;; FIXME: org-inside-LaTeX-fragment-p doesn't work when the $...$ is at
  491. ;; the beginning of the buffer - inserting "\n" is safe here though.
  492. (insert "\n" headline)
  493. (goto-char (point-min))
  494. (org-export-latex-special-chars
  495. (plist-get org-latex-options-plist :sub-superscript))
  496. (when (plist-get org-latex-options-plist :emphasize)
  497. (org-export-latex-fontify))
  498. (org-export-latex-special-keywords-maybe
  499. org-export-latex-remove-from-headines)
  500. (org-export-latex-links)
  501. (org-trim (buffer-substring-no-properties (point-min) (point-max)))))
  502. (defun org-export-latex-content (content)
  503. "Convert CONTENT string to LaTeX."
  504. (with-temp-buffer
  505. (insert content)
  506. (org-export-latex-quotation-marks)
  507. (org-export-latex-special-chars
  508. (plist-get org-latex-options-plist :sub-superscript))
  509. (when (plist-get org-latex-options-plist :emphasize)
  510. (org-export-latex-fontify))
  511. (org-export-latex-links)
  512. (org-export-latex-special-keywords)
  513. (org-export-latex-itemize)
  514. (org-export-latex-enumerate)
  515. (org-export-latex-tables
  516. (plist-get org-latex-options-plist :tables))
  517. (org-export-latex-fixed-width
  518. (plist-get org-latex-options-plist :fixed-width))
  519. (org-export-fix-invisible-strings)
  520. (buffer-substring (point-min) (point-max))))
  521. (defun org-export-fix-invisible-strings ()
  522. "Comment out (INVISIBLE) warnings."
  523. (goto-char (point-min))
  524. (while (re-search-forward "(INVISIBLE)" nil t)
  525. (replace-match "%\\&")))
  526. (defun org-export-latex-quotation-marks ()
  527. "Export question marks depending on language conventions.
  528. Local definition of the language overrides
  529. `org-export-latex-quotation-marks-convention' which overrides
  530. `org-export-default-language'."
  531. (let* ((lang (or (plist-get org-latex-options-plist :language)
  532. org-export-latex-quotation-marks-convention))
  533. (quote-rpl (if (equal lang "fr")
  534. '(("\\(\\s-\\)\"" "«~")
  535. ("\\(\\S-\\)\"" "~»")
  536. ("\\(\\s-\\)'" "`"))
  537. '(("\\(\\s-\\)\"" "``")
  538. ("\\(\\S-\\)\"" "''")
  539. ("\\(\\s-\\)'" "`")))))
  540. (mapc (lambda(l) (goto-char (point-min))
  541. (while (re-search-forward (car l) nil t)
  542. (let ((rpl (concat (match-string 1) (cadr l))))
  543. (org-latex-protect rpl)
  544. (org-if-unprotected
  545. (replace-match rpl t t))))) quote-rpl)))
  546. ;; | chars/string in Org | normal environment | math environment |
  547. ;; |-----------------------+-----------------------+-----------------------|
  548. ;; | & # % $ | \& \# \% \$ | \& \# \% \$ |
  549. ;; | { } _ ^ \ | \ { \ } \_ \^ \\ | { } _ ^ \ |
  550. ;; |-----------------------+-----------------------+-----------------------|
  551. ;; | a_b and a^b | $a_b$ and $a^b$ | a_b and a^b |
  552. ;; | a_abc and a_{abc} | $a_a$bc and $a_{abc}$ | a_abc and a_{abc} |
  553. ;; | \tau and \mu | $\tau$ and $\mu$ | \tau and \mu |
  554. ;; |-----------------------+-----------------------+-----------------------|
  555. ;; | \_ \^ | \_ \^ | \_ \^ |
  556. ;; | \(a=\mu\mbox{m}\) | \(a=\mu\mbox{m}\) | \(a=\mu\mbox{m}\) |
  557. ;; | \[\beta^2-a=0\] | \[\beta^2-a=0\] | \[\beta^2-a=0\] |
  558. ;; | $x=22\tau$ | $x=22\tau$ | $x=22\tau$ |
  559. ;; | $$\alpha=\sqrt{a^3}$$ | $$\alpha=\sqrt{a^3}$$ | $$\alpha=\sqrt{a^3}$$ |
  560. (defun org-export-latex-special-chars (sub-superscript)
  561. "Export special characters to LaTeX.
  562. If SUB-SUPERSCRIPT is non-nil, convert \\ and ^.
  563. See the `org-export-latex.el' code for a complete conversion table."
  564. (goto-char (point-min))
  565. (mapc (lambda(c)
  566. (goto-char (point-min))
  567. (while (re-search-forward c nil t)
  568. ;; Put the point where to check for org-protected
  569. (unless (get-text-property (match-beginning 2) 'org-protected)
  570. (cond ((member (match-string 2) '("\\$" "$"))
  571. (if (equal (match-string 2) "\\$")
  572. (replace-match (concat (match-string 1) "$"
  573. (match-string 3)) t t)
  574. (replace-match (concat (match-string 1) "\\$"
  575. (match-string 3)) t t)))
  576. ((member (match-string 2) '("&" "#" "%"))
  577. (if (equal (match-string 1) "\\")
  578. (replace-match (match-string 2) t t)
  579. (replace-match (concat (match-string 1) "\\"
  580. (match-string 2)) t t)))
  581. ((equal (match-string 2) "~")
  582. ;; FIXME protect ~ in links
  583. ;; (unless (get-text-property 0 'org-protected (match-string 2))
  584. ;; (unless (eq 'org-link (get-text-property 0 'face (match-string 2)))
  585. (cond ((equal (match-string 1) "\\") nil)
  586. ((eq 'org-link (get-text-property 0 'face (match-string 2)))
  587. (replace-match (concat (match-string 1) "\\~") t t))
  588. (t
  589. (replace-match
  590. (org-latex-protect
  591. (concat (match-string 1) "\\textasciitilde{}")) t t))))
  592. ((member (match-string 2) '("{" "}"))
  593. (unless (save-match-data (org-inside-LaTeX-fragment-p))
  594. (if (equal (match-string 1) "\\")
  595. (replace-match (match-string 2) t t)
  596. (replace-match (concat (match-string 1) "\\"
  597. (match-string 2)) t t)))))
  598. (unless (save-match-data (org-inside-LaTeX-fragment-p))
  599. (cond ((equal (match-string 2) "\\")
  600. (replace-match (or (save-match-data
  601. (org-export-latex-treat-backslash-char
  602. (match-string 1)
  603. (match-string 3))) "") t t))
  604. ((member (match-string 2) '("_" "^"))
  605. (replace-match (or (save-match-data
  606. (org-export-latex-treat-sub-super-char
  607. sub-superscript
  608. (match-string 1)
  609. (match-string 2)
  610. (match-string 3))) "") t t)))))))
  611. '("^\\([^\n$]*?\\|^\\)\\(\\\\?\\$\\)\\([^\n$]*\\)$"
  612. "\\([a-za-z0-9]+\\|[ \t\n]\\|\\\\\\)\\(_\\|\\^\\)\\([a-za-z0-9]+\\|[ \t\n]\\|[:punct:]\\|{[a-za-z0-9]+}\\|([a-za-z0-9]+)\\)"
  613. "\\(.\\|^\\)\\(\\\\\\)\\([ \t\n]\\|[a-za-z&#%{}]+\\)"
  614. "\\(.\\|^\\)\\(&\\)"
  615. "\\(.\\|^\\)\\(#\\)"
  616. "\\(.\\|^\\)\\(%\\)"
  617. "\\(.\\|^\\)\\({\\)"
  618. "\\(.\\|^\\)\\(}\\)"
  619. "\\(.\\|^\\)\\(~\\)")))
  620. (defun org-export-latex-treat-sub-super-char
  621. (subsup string-before char string-after)
  622. "Convert the \"_\" and \"^\" characters to LaTeX.
  623. SUBSUP corresponds to the ^: option in the #+OPTIONS line.
  624. Convert CHAR depending on STRING-BEFORE and STRING-AFTER."
  625. (cond ((equal string-before "\\")
  626. (concat string-before char string-after))
  627. ;; this is part of a math formula
  628. ((and (string-match "\\S-+" string-before)
  629. (string-match "\\S-+" string-after))
  630. (cond ((eq 'org-link (get-text-property 0 'face char))
  631. ;; (cond ((get-text-property 0 'org-protected char)
  632. (concat string-before "\\" char string-after))
  633. ((save-match-data (org-inside-LaTeX-fragment-p))
  634. (if subsup
  635. (cond ((eq 1 (length string-after))
  636. (concat string-before char string-after))
  637. ((string-match "[({]?\\([^)}]+\\)[)}]?" string-after)
  638. (format "%s%s{%s}" string-before char
  639. (match-string 1 string-after))))))
  640. ((and subsup
  641. (> (length string-after) 1)
  642. (string-match "[({]?\\([^)}]+\\)[)}]?" string-after))
  643. (format "$%s%s{%s}$" string-before char
  644. (match-string 1 string-after)))
  645. (subsup (concat "$" string-before char string-after "$"))
  646. (t (concat string-before char string-after))))
  647. (t (concat string-before "\\" char string-after))))
  648. (defun org-export-latex-treat-backslash-char (string-before string-after)
  649. "Convert the \"$\" special character to LaTeX.
  650. The conversion is made depending of STRING-BEFORE and STRING-AFTER."
  651. (cond ((member (list string-after) org-html-entities)
  652. ;; backslash is part of a special entity (like "\alpha")
  653. (concat string-before "$\\"
  654. (or (cdar (member (list string-after) org-html-entities))
  655. string-after) "$"))
  656. ((and (not (string-match "^[ \n\t]" string-after))
  657. (not (string-match "[ \n\t]\\'" string-before)))
  658. ;; backslash is inside a word
  659. (concat string-before "$\\backslash$" string-after))
  660. ((not (or (equal string-after "")
  661. (string-match "^[ \t\n]" string-after)))
  662. ;; backslash might escape a character (like \#) or a user TeX
  663. ;; macro (like \setcounter)
  664. (concat string-before "\\" string-after))
  665. ((and (string-match "^[ \t\n]" string-after)
  666. (string-match "[ \t\n]\\'" string-before))
  667. ;; backslash is alone, convert it to $\backslash$
  668. (concat string-before "$\\backslash$" string-after))
  669. (t (concat string-before "$\\backslash$" string-after))))
  670. (defun org-export-latex-fixed-width (opt)
  671. "When OPT is non-nil convert fixed-width sections to LaTeX."
  672. (goto-char (point-min))
  673. (while (re-search-forward "^[ \t]*:" nil t)
  674. (if opt
  675. (progn (goto-char (match-beginning 0))
  676. (insert "\\begin{verbatim}\n")
  677. (while (looking-at "^\\([ \t]*\\):\\(.*\\)$")
  678. (replace-match (concat (match-string 1)
  679. (match-string 2)) t t)
  680. (forward-line))
  681. (insert "\\end{verbatim}\n\n"))
  682. (progn (goto-char (match-beginning 0))
  683. (while (looking-at "^\\([ \t]*\\):\\(.*\\)$")
  684. (replace-match (concat "%" (match-string 1)
  685. (match-string 2)) t t)
  686. (forward-line))))))
  687. (defun org-export-latex-tables (opt)
  688. "When OPT is non-nil convert tables to LaTeX."
  689. (goto-char (point-min))
  690. (while (re-search-forward "^\\([ \t]*\\)|" nil t)
  691. ;; Re-align the table to update org-table-last-alignment
  692. (save-excursion (save-match-data (org-table-align)))
  693. (let (tbl-list
  694. (beg (match-beginning 0))
  695. (end (save-excursion
  696. (re-search-forward
  697. (concat "^" (regexp-quote (match-string 1))
  698. "[^|]\\|\\'") nil t) (match-beginning 0))))
  699. (beginning-of-line)
  700. (while (not (eq end (point)))
  701. (if (looking-at "[ \t]*|\\([^-|].+\\)|[ \t]*$")
  702. (push (split-string (org-trim (match-string 1)) "|") tbl-list)
  703. (push 'hline tbl-list))
  704. (forward-line))
  705. ;; comment region out instead of deleting it ?
  706. (apply 'delete-region (list beg end))
  707. (when opt (insert (orgtbl-to-latex (nreverse tbl-list)
  708. nil) "\n\n")))))
  709. (defun org-export-latex-special-keywords ()
  710. "Convert special keywords to LaTeX.
  711. Regexps are those from `org-latex-special-string-regexps'."
  712. (let ((rg org-latex-special-string-regexps) r)
  713. (while (setq r (pop rg))
  714. (goto-char (point-min))
  715. (while (re-search-forward (eval r) nil t)
  716. (replace-match (format "\\\\texttt{%s}" (match-string 0)) t)))))
  717. ;; FIXME - we need better implementation for nested lists
  718. (defun org-export-latex-list (srch0 srch1 srch2 rpl0 rpl1)
  719. "Convert lists to LaTeX."
  720. (goto-char (point-min))
  721. (while (re-search-forward srch0 nil t)
  722. (let* ((beg (match-beginning 0))
  723. (prefix (regexp-quote (match-string 1)))
  724. (end-string (when (re-search-forward srch1 nil t)
  725. (match-string 0))))
  726. (goto-char beg) (insert rpl0)
  727. (while (re-search-forward
  728. (concat "^" prefix srch2)
  729. (if (not end-string)
  730. (point-max)
  731. (save-match-data
  732. (save-excursion
  733. (re-search-forward
  734. (regexp-quote end-string) nil t)))) t)
  735. (replace-match
  736. (concat "\\item "
  737. (if (match-string 1)
  738. (format "\\texttt{%s}" (match-string 1))))
  739. t t))
  740. (goto-char (if end-string
  741. (progn (re-search-forward
  742. (regexp-quote end-string) nil t)
  743. (match-beginning 0))
  744. (point-max)))
  745. (skip-chars-backward "\n") (forward-line 2)
  746. (insert rpl1))))
  747. (defun org-export-latex-itemize ()
  748. "Convert item list to LaTeX."
  749. (org-export-latex-list
  750. "^\\([ \t]*\\)-"
  751. "^[^ \n\t-]+.*$"
  752. "- ?\\(\\[.+\\]\\)?"
  753. "\\begin{itemize}\n"
  754. "\\end{itemize}\n"))
  755. (defun org-export-latex-enumerate ()
  756. "Convert numeric list to LaTeX."
  757. (org-export-latex-list
  758. "^\\([ \t]*\\)[0-9]+[\.)] \\(\\[.+\\]\\)? ?"
  759. "^[^ \n\t0-9]+.*$"
  760. "[0-9]+[\.)] ?\\(\\[.+\\]\\)?"
  761. "\\begin{enumerate}\n"
  762. "\\end{enumerate}\n"))
  763. (defun org-export-latex-fontify ()
  764. "Convert fontification to LaTeX."
  765. (goto-char (point-min))
  766. (while (re-search-forward org-emph-re nil t)
  767. ;; The match goes one char after the *string*
  768. (unless (get-text-property (1- (point)) 'org-protected)
  769. (replace-match
  770. (concat (match-string 1)
  771. (format
  772. (org-export-latex-protect-char-in-string
  773. '("\\" "{" "}")
  774. (cadr (assoc (match-string 3)
  775. org-export-latex-emphasis-alist)))
  776. (match-string 4))
  777. (match-string 5)) t t)
  778. (backward-char))))
  779. (defun org-export-latex-protect-char-in-string (char-list string)
  780. "Add org-protected text-property to char from CHAR-LIST in STRING."
  781. (with-temp-buffer
  782. (save-match-data
  783. (insert string)
  784. (goto-char (point-min))
  785. (while (re-search-forward (regexp-opt char-list) nil t)
  786. (add-text-properties (match-beginning 0)
  787. (match-end 0) '(org-protected t)))
  788. (buffer-string))))
  789. (defun org-export-latex-links ()
  790. ;; Make sure to use the LaTeX hyperref and graphicx package
  791. ;; or send some warnings.
  792. "Convert links to LaTeX."
  793. (goto-char (point-min))
  794. (while (re-search-forward org-bracket-link-analytic-regexp nil t)
  795. (org-if-unprotected
  796. (goto-char (match-beginning 0))
  797. (let* ((re-radio org-latex-all-targets-regexp)
  798. (remove (list (match-beginning 0) (match-end 0)))
  799. (type (match-string 2))
  800. (raw-path (match-string 3))
  801. (full-raw-path (concat (match-string 1) raw-path))
  802. (desc (match-string 5))
  803. imgp radiop
  804. ;; define the path of the link
  805. (path (cond
  806. ((member type '("http" "https" "ftp"))
  807. (concat type ":" raw-path))
  808. ((and re-radio (string-match re-radio raw-path))
  809. (setq radiop t))
  810. ((equal type "mailto")
  811. (concat type ":" raw-path))
  812. ((equal type "file")
  813. (if (and (or (org-file-image-p (expand-file-name raw-path))
  814. (string-match "\\.eps$" raw-path))
  815. (equal desc full-raw-path))
  816. (setq imgp t)
  817. (progn (when (string-match "\\(.+\\)::.+" raw-path)
  818. (setq raw-path (match-string 1 raw-path)))
  819. (if (file-exists-p raw-path)
  820. (concat type "://" (expand-file-name raw-path))
  821. (concat type "://" (org-export-directory
  822. :LaTeX org-latex-options-plist)
  823. raw-path))))))))
  824. ;; process with link inserting
  825. (apply 'delete-region remove)
  826. (cond ((and imgp (plist-get org-latex-options-plist :inline-images))
  827. (insert (format "\\includegraphics[%s]{%s}"
  828. ;; image option should be set be a comment line
  829. org-export-latex-image-default-option
  830. (expand-file-name raw-path))))
  831. ;; FIXME: what about caption? image properties?
  832. (radiop (insert (format "\\hyperref[%s]{%s}" raw-path desc)))
  833. (path (insert (format "\\href{%s}{%s}" path desc)))
  834. (t (insert "\\texttt{" desc "}")))))))
  835. (defun org-latex-cleaned-string-for-export (string &rest parameters)
  836. "Cleanup a buffer STRING so that links can be created safely."
  837. (interactive)
  838. (let* ((re-radio (and org-target-link-regexp
  839. (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
  840. (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
  841. (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
  842. (re-archive (concat ":" org-archive-tag ":"))
  843. (re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>"))
  844. (htmlp (plist-get parameters :for-html))
  845. (latexp (plist-get parameters :for-LaTeX))
  846. (commentsp (plist-get parameters :comments))
  847. (inhibit-read-only t)
  848. (outline-regexp "\\*+ ")
  849. a b xx
  850. rtn p)
  851. (save-excursion
  852. (set-buffer (get-buffer-create " org-mode-tmp"))
  853. (erase-buffer)
  854. (insert string)
  855. ;; Remove license-to-kill stuff
  856. (while (setq p (text-property-any (point-min) (point-max)
  857. :org-license-to-kill t))
  858. (delete-region p (next-single-property-change p :org-license-to-kill)))
  859. (let ((org-inhibit-startup t)) (org-mode))
  860. (untabify (point-min) (point-max))
  861. ;; Get the correct stuff before the first headline
  862. (when (plist-get parameters :skip-before-1st-heading)
  863. (goto-char (point-min))
  864. (when (re-search-forward "^\\*+[ \t]" nil t)
  865. (delete-region (point-min) (match-beginning 0))
  866. (goto-char (point-min))
  867. (insert "\n")))
  868. (when (plist-get parameters :add-text)
  869. (goto-char (point-min))
  870. (insert (plist-get parameters :add-text) "\n"))
  871. ;; Get rid of archived trees
  872. (when (not (eq org-export-with-archived-trees t))
  873. (goto-char (point-min))
  874. (while (re-search-forward re-archive nil t)
  875. (if (not (org-on-heading-p t))
  876. (org-end-of-subtree t)
  877. (beginning-of-line 1)
  878. (setq a (if org-export-with-archived-trees
  879. (1+ (point-at-eol)) (point))
  880. b (org-end-of-subtree t))
  881. (if (> b a) (delete-region a b)))))
  882. ;; Get rid of property drawers
  883. (unless org-export-with-property-drawer
  884. (goto-char (point-min))
  885. (while (re-search-forward "^[ \t]*:PROPERTIES:[ \t]*\n\\([^@]*?\n\\)?[ \t]*:END:[ \t]*\n" nil t)
  886. (replace-match "")))
  887. ;; Find targets in comments and move them out of comments,
  888. ;; but mark them as targets that should be invisible
  889. (goto-char (point-min))
  890. (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
  891. (replace-match "\\1(INVISIBLE)"))
  892. ;; Specific LaTeX cleaning
  893. (when latexp
  894. (require 'org-export-latex nil t)
  895. (org-export-latex-cleaned-string))
  896. ;; Protect stuff from HTML processing
  897. (goto-char (point-min))
  898. (let ((formatters `((,htmlp "HTML" "BEGIN_HTML" "END_HTML"))) fmt)
  899. (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t)
  900. (add-text-properties (match-beginning 0) (match-end 0)
  901. '(org-protected t)))
  902. (while formatters
  903. (setq fmt (pop formatters))
  904. (when (car fmt)
  905. (goto-char (point-min))
  906. (while (re-search-forward (concat "^#\\+" (cadr fmt)
  907. ":[ \t]*\\(.*\\)") nil t)
  908. (replace-match "\\1" t)
  909. (add-text-properties
  910. (point-at-bol) (min (1+ (point-at-eol)) (point-max))
  911. '(org-protected t))))
  912. (goto-char (point-min))
  913. (while (re-search-forward
  914. (concat "^#\\+"
  915. (caddr fmt) "\\>.*\\(\\(\n.*\\)*?\n\\)#\\+"
  916. (cadddr fmt) "\\>.*\n?") nil t)
  917. (if (car fmt)
  918. (add-text-properties (match-beginning 1) (1+ (match-end 1))
  919. '(org-protected t))
  920. (delete-region (match-beginning 0) (match-end 0))))
  921. (goto-char (point-min))
  922. (while (re-search-forward re-quote nil t)
  923. (goto-char (match-beginning 0))
  924. (end-of-line 1)
  925. (add-text-properties (point) (org-end-of-subtree t)
  926. '(org-protected t)))))
  927. ;; Remove or replace comments
  928. ;; If :comments is set, use this char for commenting out comments and
  929. ;; protect them. otherwise delete them
  930. (goto-char (point-min))
  931. (while (re-search-forward "^#\\(.*\n?\\)" nil t)
  932. (if commentsp
  933. (progn (add-text-properties
  934. (match-beginning 0) (match-end 0) '(org-protected t))
  935. (replace-match (format commentsp (match-string 1)) t t))
  936. (replace-match "")))
  937. ;; Find matches for radio targets and turn them into internal links
  938. (goto-char (point-min))
  939. (when re-radio
  940. (while (re-search-forward re-radio nil t)
  941. (org-if-unprotected
  942. (replace-match "\\1[[\\2]]"))))
  943. ;; Find all links that contain a newline and put them into a single line
  944. (goto-char (point-min))
  945. (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
  946. (org-if-unprotected
  947. (replace-match "\\1 \\3")
  948. (goto-char (match-beginning 0))))
  949. ;; Convert LaTeX fragments to images
  950. (when (plist-get parameters :LaTeX-fragments)
  951. (org-format-latex
  952. (concat "ltxpng/" (file-name-sans-extension
  953. (file-name-nondirectory
  954. org-current-export-file)))
  955. org-current-export-dir nil "Creating LaTeX image %s"))
  956. (message "Exporting...")
  957. ;; Normalize links: Convert angle and plain links into bracket links
  958. ;; Expand link abbreviations
  959. (goto-char (point-min))
  960. (while (re-search-forward re-plain-link nil t)
  961. (goto-char (1- (match-end 0)))
  962. (org-if-unprotected
  963. (let* ((s (concat (match-string 1) "[[" (match-string 2)
  964. ":" (match-string 3) "]]")))
  965. ;; added 'org-protected property to links
  966. (put-text-property 0 (length s) 'face 'org-link s)
  967. ;; (add-text-properties 0 (length s) '(org-protected t) s)
  968. (replace-match s t t))))
  969. (goto-char (point-min))
  970. (while (re-search-forward re-angle-link nil t)
  971. (goto-char (1- (match-end 0)))
  972. (org-if-unprotected
  973. (let* ((s (concat (match-string 1) "[[" (match-string 2)
  974. ":" (match-string 3) "]]")))
  975. (put-text-property 0 (length s) 'face 'org-link s)
  976. ;; (add-text-properties 0 (length s) '(org-protected t) s)
  977. (replace-match s t t))))
  978. (goto-char (point-min))
  979. (while (re-search-forward org-bracket-link-regexp nil t)
  980. (org-if-unprotected
  981. (let* ((s (concat "[[" (setq xx (save-match-data
  982. (org-link-expand-abbrev (match-string 1))))
  983. "]"
  984. (if (match-end 3)
  985. (match-string 2)
  986. (concat "[" xx "]"))
  987. "]")))
  988. (put-text-property 0 (length s) 'face 'org-link s)
  989. ;; (add-text-properties 0 (length s) '(org-protected t) s)
  990. (replace-match s t t))))
  991. ;; Find multiline emphasis and put them into single line
  992. (when (plist-get parameters :emph-multiline)
  993. (goto-char (point-min))
  994. (while (re-search-forward org-emph-re nil t)
  995. (if (not (= (char-after (match-beginning 3))
  996. (char-after (match-beginning 4))))
  997. (org-if-unprotected
  998. (subst-char-in-region (match-beginning 0) (match-end 0)
  999. ?\n ?\ t)
  1000. (goto-char (1- (match-end 0))))
  1001. (goto-char (1+ (match-beginning 0))))))
  1002. (setq rtn (buffer-string)))
  1003. (kill-buffer " org-mode-tmp")
  1004. rtn))
  1005. (defsubst org-latex-protect (string)
  1006. (add-text-properties 0 (length string) '(org-protected t) string)
  1007. string)
  1008. (defun org-export-latex-cleaned-string ()
  1009. "Clean stuff in the LaTeX export."
  1010. ;; preserve line breaks
  1011. (goto-char (point-min))
  1012. (while (re-search-forward "\\\\\\\\" nil t)
  1013. (add-text-properties (match-beginning 0) (match-end 0)
  1014. '(org-protected t)))
  1015. ;; convert LaTeX to @LaTeX{}
  1016. (goto-char (point-min))
  1017. (let ((case-fold-search nil) rpl)
  1018. (while (re-search-forward "\\([^+_]\\)LaTeX" nil t)
  1019. (replace-match (org-latex-protect
  1020. (concat (match-string 1) "\\LaTeX{}")) t t)))
  1021. ;; convert horizontal rules
  1022. (goto-char (point-min))
  1023. (while (re-search-forward "^----+.$" nil t)
  1024. (replace-match (org-latex-protect "\\hrule") t t))
  1025. ;; Remove COMMENT subtrees
  1026. ;; What about QUOTE subtrees?
  1027. (goto-char (point-min))
  1028. (while (re-search-forward
  1029. (concat "^\\*+ \\(" org-comment-string "\\)")
  1030. nil t)
  1031. (beginning-of-line)
  1032. (org-cut-subtree))
  1033. ;; protect LaTeX \commands{...}
  1034. (goto-char (point-min))
  1035. (while (re-search-forward "\\\\[a-z]+{.+}" nil t)
  1036. (add-text-properties (match-beginning 0) (match-end 0)
  1037. '(org-protected t)))
  1038. ;; Replace radio links
  1039. (goto-char (point-min))
  1040. (let ((search (concat "<<<?" org-latex-all-targets-regexp ">?>>")))
  1041. (while (re-search-forward search nil t)
  1042. (replace-match
  1043. (org-latex-protect (format "\\label{%s}" (match-string 1))) t t)))
  1044. ;; delete @<br /> cookies
  1045. (goto-char (point-min))
  1046. (while (re-search-forward "@<[^<>\n]*>" nil t)
  1047. (replace-match ""))
  1048. ;; add #+BEGIN_LaTeX before any \begin{...}
  1049. (goto-char (point-min))
  1050. (while (re-search-forward "^ *\\\\begin{" nil t)
  1051. (replace-match "#+BEGIN_LaTeX:\n\\&" t))
  1052. ;; add #+END_LaTeX after any \end{...}
  1053. (goto-char (point-min))
  1054. (while (re-search-forward "^ *\\\\end{.+}.*$" nil t)
  1055. (replace-match "\\&\n#+END_LaTeX" t))
  1056. ;; When converting to LaTeX, replace footnotes
  1057. ;; FIXME: don't protect footnotes from conversion
  1058. (when (plist-get org-latex-options-plist :footnotes)
  1059. (goto-char (point-min))
  1060. (while (re-search-forward "\\[[0-9]+\\]" nil t)
  1061. (when (save-match-data
  1062. (save-excursion (beginning-of-line)
  1063. (looking-at "[^:|]")))
  1064. (let ((foot-beg (match-beginning 0))
  1065. (foot-end (match-end 0))
  1066. (foot-prefix (match-string 0))
  1067. footnote footnote-rpl)
  1068. (when (and (re-search-forward (regexp-quote foot-prefix) nil t))
  1069. (replace-match "")
  1070. (let ((end (save-excursion
  1071. (if (re-search-forward "^$\\|\\[[0-9]+\\]" nil t)
  1072. (match-beginning 0) (point-max)))))
  1073. (setq footnote (concat
  1074. (org-trim (buffer-substring (point) end))
  1075. ;; FIXME stupid workaround for cases where
  1076. ;; `org-bracket-link-analytic-regexp' matches
  1077. ;; }. as part of the link.
  1078. " "))
  1079. (delete-region (point) end)))
  1080. (goto-char foot-beg)
  1081. (delete-region foot-beg foot-end)
  1082. (setq footnote-rpl (format "\\footnote{%s}" footnote))
  1083. ;; FIXME Remove
  1084. ;; (add-text-properties 0 1 '(org-protected t) footnote-rpl)
  1085. (add-text-properties 0 10 '(org-protected t) footnote-rpl)
  1086. ;; FIXME: why protecting the content of a footnote?
  1087. (add-text-properties (1- (length footnote-rpl))
  1088. (length footnote-rpl)
  1089. '(org-protected t) footnote-rpl)
  1090. (insert footnote-rpl))))
  1091. ;; Replace footnote section tag for LaTeX
  1092. (goto-char (point-min))
  1093. (while (re-search-forward
  1094. (concat "^" footnote-section-tag-regexp) nil t)
  1095. (replace-match "")))
  1096. ;; Protect stuff from LaTeX processing.
  1097. ;; We will get rid on this once org.el integrate org-export-latex.el
  1098. ;; FIXME: #+LaTeX should be aware of the preceeding indentation in lists
  1099. (goto-char (point-min))
  1100. (let ((formatters `((,latexp "LaTeX" "BEGIN_LaTeX" "END_LaTeX"))) fmt)
  1101. (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t)
  1102. (add-text-properties (match-beginning 0) (match-end 0)
  1103. '(org-protected t)))
  1104. (while formatters
  1105. (setq fmt (pop formatters))
  1106. (when (car fmt)
  1107. (goto-char (point-min))
  1108. (while (re-search-forward (concat "^#\\+" (cadr fmt)
  1109. ":[ \t]*\\(.*\\)") nil t)
  1110. (replace-match "\\1" t)
  1111. (add-text-properties
  1112. (point-at-bol) (min (1+ (point-at-eol)) (point-max))
  1113. '(org-protected t))))
  1114. (goto-char (point-min))
  1115. (while (re-search-forward
  1116. (concat "^#\\+"
  1117. (caddr fmt) "\\>.*\\(\\(\n.*\\)*?\n\\)#\\+"
  1118. (cadddr fmt) "\\>.*\n?") nil t)
  1119. (if (car fmt)
  1120. (add-text-properties (match-beginning 1) (1+ (match-end 1))
  1121. '(org-protected t))
  1122. (delete-region (match-beginning 0) (match-end 0))))
  1123. (goto-char (point-min))
  1124. (while (re-search-forward re-quote nil t)
  1125. (goto-char (match-beginning 0))
  1126. (end-of-line 1)
  1127. (add-text-properties (point) (org-end-of-subtree t)
  1128. '(org-protected t))))))
  1129. (provide 'org-export-latex)
  1130. ;;; org-export-latex.el ends here