summaryrefslogtreecommitdiff
path: root/lisp/ox-latex.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/ox-latex.el')
-rw-r--r--lisp/ox-latex.el800
1 files changed, 466 insertions, 334 deletions
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 121a675..57ec1d2 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1,4 +1,4 @@
-;;; ox-latex.el --- LaTeX Back-End for Org Export Engine
+;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: t; -*-
;; Copyright (C) 2011-2016 Free Software Foundation, Inc.
@@ -26,7 +26,7 @@
;;; Code:
-(eval-when-compile (require 'cl))
+(require 'cl-lib)
(require 'ox)
(require 'ox-publish)
@@ -90,7 +90,6 @@
;; Pseudo objects and elements.
(latex-math-block . org-latex-math-block)
(latex-matrices . org-latex-matrices))
- :export-block '("LATEX" "TEX")
:menu-entry
'(?l "Export to LaTeX"
((?L "As LaTeX buffer" org-latex-export-as-latex)
@@ -119,6 +118,7 @@
(:latex-default-table-environment nil nil org-latex-default-table-environment)
(:latex-default-table-mode nil nil org-latex-default-table-mode)
(:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format)
+ (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format)
(:latex-footnote-separator nil nil org-latex-footnote-separator)
(:latex-format-drawer-function nil nil org-latex-format-drawer-function)
(:latex-format-headline-function nil nil org-latex-format-headline-function)
@@ -127,6 +127,7 @@
(:latex-image-default-height nil nil org-latex-image-default-height)
(:latex-image-default-option nil nil org-latex-image-default-option)
(:latex-image-default-width nil nil org-latex-image-default-width)
+ (:latex-images-centered nil nil org-latex-images-centered)
(:latex-inactive-timestamp-format nil nil org-latex-inactive-timestamp-format)
(:latex-inline-image-rules nil nil org-latex-inline-image-rules)
(:latex-link-with-unknown-path-format nil nil org-latex-link-with-unknown-path-format)
@@ -144,6 +145,7 @@
(:latex-text-markup-alist nil nil org-latex-text-markup-alist)
(:latex-title-command nil nil org-latex-title-command)
(:latex-toc-command nil nil org-latex-toc-command)
+ (:latex-compiler "LATEX_COMPILER" nil org-latex-compiler)
;; Redefine regular options.
(:date "DATE" nil "\\today" parse)))
@@ -327,7 +329,7 @@ Otherwise, place it near the end. When value is a list of
symbols, put caption above selected elements only. Allowed
symbols are: `image', `table', `src-block' and `special-block'."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type '(choice
(const :tag "For all elements" t)
@@ -363,9 +365,9 @@ For example, when this variable is non-nil, a headline like this:
:CUSTOM_ID: sec:foo
:END:
This is section [[#sec:foo]].
- #+BEGIN_LATEX
+ #+BEGIN_EXPORT latex
And this is still section \\ref{sec:foo}.
- #+END_LATEX
+ #+END_EXPORT
will be exported to LaTeX as:
@@ -390,7 +392,7 @@ labeling scheme to generate labels and resolve links into proper
references."
:group 'org-export-latex
:type 'boolean
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3"))
;;;; Preamble
@@ -572,14 +574,14 @@ precedence over this variable."
The format string should have at most one \"%s\"-expression,
which is replaced with the subtitle."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type '(string :tag "Format string"))
(defcustom org-latex-subtitle-separate nil
"Non-nil means the subtitle is not typeset as part of title."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type 'boolean)
@@ -616,12 +618,10 @@ inserted.
Setting :latex-hyperref-template in publishing projects will take
precedence over this variable."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type '(choice (const :tag "No template" nil)
(string :tag "Format string")))
-(define-obsolete-variable-alias
- 'org-latex-with-hyperref 'org-latex-hyperref-template "25.1")
;;;; Headline
@@ -651,6 +651,16 @@ The function result will be used in the section format string."
:group 'org-export-latex
:type 'string)
+(defcustom org-latex-footnote-defined-format "\\textsuperscript{\\ref{%s}}"
+ "Format string used to format reference to footnote already defined.
+%s will be replaced by the label of the referred footnote."
+ :group 'org-export-latex
+ :type '(choice
+ (const :tag "Use plain superscript (default)" "\\textsuperscript{\\ref{%s}}")
+ (const :tag "Use Memoir/KOMA-Script footref" "\\footref{%s}")
+ (string :tag "Other format string"))
+ :version "25.2"
+ :package-version '(Org . "9.0"))
;;;; Timestamps
@@ -672,6 +682,14 @@ The function result will be used in the section format string."
;;;; Links
+(defcustom org-latex-images-centered t
+ "When non-nil, images are centered."
+ :group 'org-export-latex
+ :version "25.2"
+ :package-version '(Org . "9.0")
+ :type 'boolean
+ :safe #'booleanp)
+
(defcustom org-latex-image-default-option ""
"Default option for images."
:group 'org-export-latex
@@ -697,10 +715,13 @@ environment."
:package-version '(Org . "8.0")
:type 'string)
-(defcustom org-latex-default-figure-position "htb"
- "Default position for latex figures."
+(defcustom org-latex-default-figure-position "htbp"
+ "Default position for LaTeX figures."
:group 'org-export-latex
- :type 'string)
+ :type 'string
+ :version "25.2"
+ :package-version '(Org . "9.0")
+ :safe #'stringp)
(defcustom org-latex-inline-image-rules
'(("file" . "\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\|tikz\\|pgf\\|svg\\)\\'"))
@@ -821,7 +842,7 @@ to typeset and try to protect special characters.
If no association can be found for a given markup, text will be
returned as-is."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type 'alist
:options '(bold code italic strike-through underline verbatim))
@@ -829,8 +850,7 @@ returned as-is."
;;;; Drawers
-(defcustom org-latex-format-drawer-function
- (lambda (name contents) contents)
+(defcustom org-latex-format-drawer-function (lambda (_ contents) contents)
"Function called to format a drawer in LaTeX code.
The function must accept two parameters:
@@ -864,7 +884,7 @@ The function must accept seven parameters:
The function should return the string to be exported."
:group 'org-export-latex
:type 'function
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3"))
@@ -923,7 +943,8 @@ into previewing problems, please consult
(gnuplot "Gnuplot")
(ocaml "Caml") (caml "Caml")
(sql "SQL") (sqlite "sql")
- (makefile "make"))
+ (makefile "make")
+ (R "r"))
"Alist mapping languages to their listing language counterpart.
The key is a symbol, the major mode symbol without the \"-mode\".
The value is the string that should be inserted as the language
@@ -1020,34 +1041,116 @@ block-specific options, you may use the following syntax:
(string :tag "Minted option name ")
(string :tag "Minted option value"))))
-(defvar org-latex-custom-lang-environments nil
+(defcustom org-latex-custom-lang-environments nil
"Alist mapping languages to language-specific LaTeX environments.
It is used during export of src blocks by the listings and minted
-latex packages. For example,
+latex packages. The environment may be a simple string, composed of
+only letters and numbers. In this case, the string is directly the
+name of the latex environment to use. The environment may also be
+a format string. In this case the format string will be directly
+exported. This format string may contain these elements:
+
+ %s for the formatted source
+ %c for the caption
+ %f for the float attribute
+ %l for an appropriate label
+ %o for the LaTeX attributes
+
+For example,
(setq org-latex-custom-lang-environments
- '((python \"pythoncode\")))
+ '((python \"pythoncode\")
+ (ocaml \"\\\\begin{listing}
+\\\\begin{minted}[%o]{ocaml}
+%s\\\\end{minted}
+\\\\caption{%c}
+\\\\label{%l}\")))
-would have the effect that if org encounters begin_src python
-during latex export it will output
+would have the effect that if Org encounters a Python source block
+during LaTeX export it will produce
\\begin{pythoncode}
<src block body>
- \\end{pythoncode}")
+ \\end{pythoncode}
+
+and if Org encounters an Ocaml source block during LaTeX export it
+will produce
+
+ \\begin{listing}
+ \\begin{minted}[<attr_latex options>]{ocaml}
+ <src block body>
+ \\end{minted}
+ \\caption{<caption>}
+ \\label{<label>}
+ \\end{listing}"
+ :group 'org-export-latex
+ :type '(repeat
+ (list
+ (symbol :tag "Language name ")
+ (string :tag "Environment name or format string")))
+ :version "25.2"
+ :package-version '(Org . "9.0"))
;;;; Compilation
+(defcustom org-latex-compiler-file-string "%% Intended LaTeX compiler: %s\n"
+ "LaTeX compiler format-string.
+See also `org-latex-compiler'."
+ :group 'org-export-latex
+ :type '(choice
+ (const :tag "Comment" "%% Intended LaTeX compiler: %s\n")
+ (const :tag "latex-mode file variable" "%% -*- latex-run-command: %s -*-\n")
+ (const :tag "AUCTeX file variable" "%% -*- LaTeX-command: %s -*-\n")
+ (string :tag "custom format" "%% %s"))
+ :version "25.2"
+ :package-version '(Org . "9.0"))
+
+(defcustom org-latex-compiler "pdflatex"
+ "LaTeX compiler to use.
+
+Must be an element in `org-latex-compilers' or the empty quote.
+Can also be set in buffers via #+LATEX_COMPILER. See also
+`org-latex-compiler-file-string'."
+ :group 'org-export-latex
+ :type '(choice
+ (const :tag "pdfLaTeX" "pdflatex")
+ (const :tag "XeLaTeX" "xelatex")
+ (const :tag "LuaLaTeX" "lualatex")
+ (const :tag "Unset" ""))
+ :version "25.2"
+ :package-version '(Org . "9.0"))
+
+(defconst org-latex-compilers '("pdflatex" "xelatex" "lualatex")
+ "Known LaTeX compilers.
+See also `org-latex-compiler'.")
+
+(defcustom org-latex-bib-compiler "bibtex"
+ "Command to process a LaTeX file's bibliography.
+
+The shorthand %bib in `org-latex-pdf-process' is replaced with
+this value.
+
+A better approach is to use a compiler suit such as `latexmk'."
+ :group 'org-export-latex
+ :type '(choice (const :tag "BibTeX" "bibtex")
+ (const :tag "Biber" "biber")
+ (string :tag "Other process"))
+ :version "25.2"
+ :package-version '(Org . "9.0"))
+
(defcustom org-latex-pdf-process
- '("pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f")
+ '("%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f")
"Commands to process a LaTeX file to a PDF file.
This is a list of strings, each of them will be given to the
shell as a command. %f in the command will be replaced by the
full file name, %b by the file base name (i.e. without directory
-and extension parts) and %o by the base directory of the file.
+and extension parts), %o by the base directory of the file,
+%latex is the LaTeX compiler (see `org-latex-compiler'), and %bib
+is the BibTeX-like compiler (see `org-latex-bib-compiler').
The reason why this is a list is that it usually takes several
runs of `pdflatex', maybe mixed with a call to `bibtex'. Org
@@ -1055,18 +1158,8 @@ does not have a clever mechanism to detect which of these
commands have to be run to get to a stable result, and it also
does not do any error checking.
-By default, Org uses 3 runs of `pdflatex' to do the processing.
-If you have texi2dvi on your system and if that does not cause
-the infamous egrep/locale bug:
-
- http://lists.gnu.org/archive/html/bug-texinfo/2010-03/msg00031.html
-
-then `texi2dvi' is the superior choice as it automates the LaTeX
-build process by calling the \"correct\" combinations of
-auxiliary programs. Org does offer `texi2dvi' as one of the
-customize options. Alternatively, `rubber' and `latexmk' also
-provide similar functionality. The latter supports `biber' out
-of the box.
+Consider a smart LaTeX compiler such as `texi2dvi' or `latexmk',
+which calls the \"correct\" combinations of auxiliary programs.
Alternatively, this may be a Lisp function that does the
processing, so you could use this to apply the machinery of
@@ -1076,36 +1169,22 @@ file name as its single argument."
:type '(choice
(repeat :tag "Shell command sequence"
(string :tag "Shell command"))
- (const :tag "2 runs of pdflatex"
- ("pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f"))
- (const :tag "3 runs of pdflatex"
- ("pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f"))
- (const :tag "pdflatex,bibtex,pdflatex,pdflatex"
- ("pdflatex -interaction nonstopmode -output-directory %o %f"
- "bibtex %b"
- "pdflatex -interaction nonstopmode -output-directory %o %f"
- "pdflatex -interaction nonstopmode -output-directory %o %f"))
- (const :tag "2 runs of xelatex"
- ("xelatex -interaction nonstopmode -output-directory %o %f"
- "xelatex -interaction nonstopmode -output-directory %o %f"))
- (const :tag "3 runs of xelatex"
- ("xelatex -interaction nonstopmode -output-directory %o %f"
- "xelatex -interaction nonstopmode -output-directory %o %f"
- "xelatex -interaction nonstopmode -output-directory %o %f"))
- (const :tag "xelatex,bibtex,xelatex,xelatex"
- ("xelatex -interaction nonstopmode -output-directory %o %f"
- "bibtex %b"
- "xelatex -interaction nonstopmode -output-directory %o %f"
- "xelatex -interaction nonstopmode -output-directory %o %f"))
+ (const :tag "2 runs of latex"
+ ("%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f"))
+ (const :tag "3 runs of latex"
+ ("%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f"))
+ (const :tag "latex,bibtex,latex,latex"
+ ("%latex -interaction nonstopmode -output-directory %o %f"
+ "%bib %b"
+ "%latex -interaction nonstopmode -output-directory %o %f"
+ "%latex -interaction nonstopmode -output-directory %o %f"))
(const :tag "texi2dvi"
- ("texi2dvi -p -b -V %f"))
- (const :tag "rubber"
- ("rubber -d --into %o %f"))
+ ("LATEX=\"%latex\" texi2dvi -p -b -V %f"))
(const :tag "latexmk"
- ("latexmk -g -pdf %f"))
+ ("latexmk -g -pdflatex=\"%latex\" %f"))
(function)))
(defcustom org-latex-logfiles-extensions
@@ -1115,7 +1194,7 @@ file name as its single argument."
The logfiles will be removed if `org-latex-remove-logfiles' is
non-nil."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type '(repeat (string :tag "Extension")))
@@ -1139,7 +1218,7 @@ The regular expressions are used to find possible warnings in the
log of a latex-run. These warnings will be reported after
calling `org-latex-compile'."
:group 'org-export-latex
- :version "25.1"
+ :version "25.2"
:package-version '(Org . "8.3")
:type '(repeat
(cons
@@ -1171,7 +1250,7 @@ Eventually, if FULL is non-nil, wrap label within \"\\label{}\"."
(let* ((type (org-element-type datum))
(user-label
(org-element-property
- (case type
+ (cl-case type
((headline inlinetask) :CUSTOM_ID)
(target :value)
(otherwise :name))
@@ -1180,11 +1259,11 @@ Eventually, if FULL is non-nil, wrap label within \"\\label{}\"."
(and (or user-label force)
(if (and user-label (plist-get info :latex-prefer-user-labels))
user-label
- (concat (case type
+ (concat (cl-case type
(headline "sec:")
(table "tab:")
(latex-environment
- (and (org-string-match-p
+ (and (string-match-p
org-latex-math-environments-re
(org-element-property :value datum))
"eq:"))
@@ -1222,13 +1301,13 @@ For non-floats, see `org-latex--wrap-label'."
((org-string-nw-p caption-from-attr-latex)
(concat caption-from-attr-latex "\n"))
((and (not main) (equal label "")) "")
- ((not main) (concat label "\n"))
+ ((not main) label)
;; Option caption format with short name.
(t
(format (if nonfloat "\\captionof{%s}%s{%s%s}\n"
"\\caption%s%s{%s%s}\n")
(if nonfloat
- (case type
+ (cl-case type
(paragraph "figure")
(src-block (if (plist-get info :latex-listings)
"listing"
@@ -1280,8 +1359,8 @@ Return the new header."
header
(let ((options (save-match-data
(org-split-string (match-string 1 header) ",[ \t]*")))
- (language (cdr (assoc language-code
- org-latex-babel-language-alist))))
+ (language (cdr (assoc-string language-code
+ org-latex-babel-language-alist t))))
;; If LANGUAGE is already loaded, return header without AUTO.
;; Otherwise, replace AUTO with language or append language if
;; AUTO is not present.
@@ -1346,13 +1425,37 @@ Return the new header."
""))
t t header 0)))))
+(defun org-latex--remove-packages (pkg-alist info)
+ "Remove packages based on the current LaTeX compiler.
+
+If the fourth argument of an element is set in pkg-alist, and it
+is not a member of the LaTeX compiler of the document, the packages
+is removed. See also `org-latex-compiler'.
+
+Return modified pkg-alist."
+ (let ((compiler (or (plist-get info :latex-compiler) "")))
+ (if (member-ignore-case compiler org-latex-compilers)
+ (delq nil
+ (mapcar
+ (lambda (pkg)
+ (unless (and
+ (listp pkg)
+ (let ((third (nth 3 pkg)))
+ (and third
+ (not (member-ignore-case
+ compiler
+ (if (listp third) third (list third)))))))
+ pkg))
+ pkg-alist))
+ pkg-alist)))
+
(defun org-latex--find-verb-separator (s)
"Return a character not used in string S.
This is used to choose a separator for constructs like \\verb."
(let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
- (loop for c across ll
- when (not (string-match (regexp-quote (char-to-string c)) s))
- return (char-to-string c))))
+ (cl-loop for c across ll
+ when (not (string-match (regexp-quote (char-to-string c)) s))
+ return (char-to-string c))))
(defun org-latex--make-option-string (options)
"Return a comma separated string of keywords and values.
@@ -1360,9 +1463,10 @@ OPTIONS is an alist where the key is the options keyword as
a string, and the value a list containing the keyword value, or
nil."
(mapconcat (lambda (pair)
- (concat (first pair)
- (when (> (length (second pair)) 0)
- (concat "=" (second pair)))))
+ (pcase-let ((`(,keyword ,value) pair))
+ (concat keyword
+ (and (> (length value) 0)
+ (concat "=" value)))))
options
","))
@@ -1394,7 +1498,7 @@ should not be used for floats. See
INFO is a plist used as a communication channel. See
`org-latex-text-markup-alist' for details."
(let ((fmt (cdr (assq markup (plist-get info :latex-text-markup-alist)))))
- (case fmt
+ (cl-case fmt
;; No format string: Return raw text.
((nil) text)
;; Handle the `verb' special case: Find an appropriate separator
@@ -1416,38 +1520,35 @@ INFO is a plist used as a communication channel. See
INFO is a plist used as a communication channel.
-Footnotes definitions are returned within \"\\footnotetxt{}\"
+Footnotes definitions are returned within \"\\footnotetext{}\"
commands.
This function is used within constructs that don't support
-\"\\footnote{}\" command (i.e. an item's tag). In that case,
+\"\\footnote{}\" command (e.g., an item tag). In that case,
\"\\footnotemark\" is used within the construct and the function
just outside of it."
(mapconcat
(lambda (ref)
- (format
- "\\footnotetext[%s]{%s}"
- (org-export-get-footnote-number ref info)
- (org-trim
- (org-export-data
- (org-export-get-footnote-definition ref info) info))))
+ (let ((def (org-export-get-footnote-definition ref info)))
+ (format "\\footnotetext[%d]{%s%s}"
+ (org-export-get-footnote-number ref info)
+ (org-trim (org-latex--label def info t t))
+ (org-trim (org-export-data def info)))))
;; Find every footnote reference in ELEMENT.
- (let* (all-refs
- search-refs ; For byte-compiler.
- (search-refs
- (function
- (lambda (data)
- ;; Return a list of all footnote references never seen
- ;; before in DATA.
- (org-element-map data 'footnote-reference
- (lambda (ref)
- (when (org-export-footnote-first-reference-p ref info)
- (push ref all-refs)
- (when (eq (org-element-property :type ref) 'standard)
- (funcall search-refs
- (org-export-get-footnote-definition ref info)))))
- info)
- (reverse all-refs)))))
+ (letrec ((all-refs nil)
+ (search-refs
+ (lambda (data)
+ ;; Return a list of all footnote references never seen
+ ;; before in DATA.
+ (org-element-map data 'footnote-reference
+ (lambda (ref)
+ (when (org-export-footnote-first-reference-p ref info)
+ (push ref all-refs)
+ (when (eq (org-element-property :type ref) 'standard)
+ (funcall search-refs
+ (org-export-get-footnote-definition ref info)))))
+ info)
+ (reverse all-refs))))
(funcall search-refs element))
""))
@@ -1460,7 +1561,8 @@ INFO is a plist used as a communication channel."
"Create a format-spec for document meta-data.
INFO is a plist used as a communication channel."
(let ((language (let ((lang (plist-get info :language)))
- (or (cdr (assoc lang org-latex-babel-language-alist))
+ (or (cdr (assoc-string lang org-latex-babel-language-alist t))
+ (nth 1 (assoc-string lang org-latex-polyglossia-language-alist t))
lang))))
`((?a . ,(org-export-data (plist-get info :author) info))
(?t . ,(org-export-data (plist-get info :title) info))
@@ -1475,8 +1577,8 @@ INFO is a plist used as a communication channel."
(?L . ,(capitalize language))
(?D . ,(org-export-get-date info)))))
-(defun org-latex--make-header (info)
- "Return a formatted LaTeX header.
+(defun org-latex--make-preamble (info)
+ "Return a formatted LaTeX preamble.
INFO is a plist used as a communication channel."
(let* ((class (plist-get info :latex-class))
(class-options (plist-get info :latex-class-options))
@@ -1495,14 +1597,25 @@ INFO is a plist used as a communication channel."
(org-element-normalize-string
(org-splice-latex-header
document-class-string
- org-latex-default-packages-alist
- org-latex-packages-alist nil
- (concat (org-element-normalize-string
- (plist-get info :latex-header))
- (plist-get info :latex-header-extra)))))
+ (org-latex--remove-packages
+ org-latex-default-packages-alist info)
+ (org-latex--remove-packages
+ org-latex-packages-alist info)
+ nil
+ (mapconcat 'org-element-normalize-string
+ (list (plist-get info :latex-header)
+ (plist-get info :latex-header-extra)) ""))))
info)
info))))
+(defun org-latex--insert-compiler (info)
+ "Insert LaTeX_compiler info into the document.
+INFO is a plist used as a communication channel."
+ (let ((compiler (plist-get info :latex-compiler)))
+ (and (org-string-nw-p org-latex-compiler-file-string)
+ (member (or compiler "") org-latex-compilers)
+ (format org-latex-compiler-file-string compiler))))
+
;;; Template
@@ -1516,8 +1629,10 @@ holding export options."
;; Time-stamp.
(and (plist-get info :time-stamp-file)
(format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
+ ;; LaTeX compiler.
+ (org-latex--insert-compiler info)
;; Document class and packages.
- (org-latex--make-header info)
+ (org-latex--make-preamble info)
;; Possibly limit depth for headline numbering.
(let ((sec-num (plist-get info :section-numbers)))
(when (integerp sec-num)
@@ -1583,7 +1698,7 @@ holding export options."
;;;; Bold
-(defun org-latex-bold (bold contents info)
+(defun org-latex-bold (_bold contents info)
"Transcode BOLD from Org to LaTeX.
CONTENTS is the text with bold markup. INFO is a plist holding
contextual information."
@@ -1602,7 +1717,7 @@ holding contextual information."
;;;; Clock
-(defun org-latex-clock (clock contents info)
+(defun org-latex-clock (clock _contents info)
"Transcode a CLOCK element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
@@ -1618,7 +1733,7 @@ information."
;;;; Code
-(defun org-latex-code (code contents info)
+(defun org-latex-code (code _contents info)
"Transcode a CODE object from Org to LaTeX.
CONTENTS is nil. INFO is a plist used as a communication
channel."
@@ -1648,7 +1763,7 @@ holding contextual information. See `org-export-data'."
;;;; Entity
-(defun org-latex-entity (entity contents info)
+(defun org-latex-entity (entity _contents _info)
"Transcode an ENTITY object from Org to LaTeX.
CONTENTS are the definition itself. INFO is a plist holding
contextual information."
@@ -1657,7 +1772,7 @@ contextual information."
;;;; Example Block
-(defun org-latex-example-block (example-block contents info)
+(defun org-latex-example-block (example-block _contents info)
"Transcode an EXAMPLE-BLOCK element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
@@ -1676,7 +1791,7 @@ information."
;;;; Export Block
-(defun org-latex-export-block (export-block contents info)
+(defun org-latex-export-block (export-block _contents _info)
"Transcode a EXPORT-BLOCK element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(when (member (org-element-property :type export-block) '("LATEX" "TEX"))
@@ -1685,7 +1800,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Export Snippet
-(defun org-latex-export-snippet (export-snippet contents info)
+(defun org-latex-export-snippet (export-snippet _contents _info)
"Transcode a EXPORT-SNIPPET object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(when (eq (org-export-snippet-backend export-snippet) 'latex)
@@ -1694,7 +1809,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Fixed Width
-(defun org-latex-fixed-width (fixed-width contents info)
+(defun org-latex-fixed-width (fixed-width _contents info)
"Transcode a FIXED-WIDTH element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(org-latex--wrap-label
@@ -1707,33 +1822,47 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Footnote Reference
-(defun org-latex-footnote-reference (footnote-reference contents info)
+(defun org-latex-footnote-reference (footnote-reference _contents info)
"Transcode a FOOTNOTE-REFERENCE element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
- (concat
- ;; Insert separator between two footnotes in a row.
- (let ((prev (org-export-get-previous-element footnote-reference info)))
- (when (eq (org-element-type prev) 'footnote-reference)
- (plist-get info :latex-footnote-separator)))
- (cond
- ;; Use \footnotemark if the footnote has already been defined.
- ((not (org-export-footnote-first-reference-p footnote-reference info))
- (format "\\footnotemark[%s]{}"
- (org-export-get-footnote-number footnote-reference info)))
- ;; Use \footnotemark if reference is within another footnote
- ;; reference, footnote definition or table cell.
- ((org-element-lineage footnote-reference
- '(footnote-reference footnote-definition table-cell))
- "\\footnotemark")
- ;; Otherwise, define it with \footnote command.
- (t
- (let ((def (org-export-get-footnote-definition footnote-reference info)))
- (concat
- (format "\\footnote{%s}" (org-trim (org-export-data def info)))
- ;; Retrieve all footnote references within the footnote and
- ;; add their definition after it, since LaTeX doesn't support
- ;; them inside.
- (org-latex--delayed-footnotes-definitions def info)))))))
+ (let ((label (org-element-property :label footnote-reference)))
+ (concat
+ ;; Insert separator between two footnotes in a row.
+ (let ((prev (org-export-get-previous-element footnote-reference info)))
+ (when (eq (org-element-type prev) 'footnote-reference)
+ (plist-get info :latex-footnote-separator)))
+ (cond
+ ;; Use `:latex-footnote-defined-format' if the footnote has
+ ;; already been defined.
+ ((not (org-export-footnote-first-reference-p footnote-reference info))
+ (format (plist-get info :latex-footnote-defined-format)
+ (org-latex--label
+ (org-export-get-footnote-definition footnote-reference info)
+ info t)))
+ ;; Use \footnotemark if reference is within another footnote
+ ;; reference, footnote definition or table cell.
+ ((org-element-lineage footnote-reference
+ '(footnote-reference footnote-definition table-cell))
+ "\\footnotemark")
+ ;; Otherwise, define it with \footnote command.
+ (t
+ (let ((def (org-export-get-footnote-definition footnote-reference info)))
+ (concat
+ (format "\\footnote{%s%s}" (org-trim (org-export-data def info))
+ ;; Only insert a \label if there exist another
+ ;; reference to def.
+ (cond ((not label) "")
+ ((org-element-map (plist-get info :parse-tree) 'footnote-reference
+ (lambda (f)
+ (and (not (eq f footnote-reference))
+ (equal (org-element-property :label f) label)
+ (org-trim (org-latex--label def info t t))))
+ info t))
+ (t "")))
+ ;; Retrieve all footnote references within the footnote and
+ ;; add their definition after it, since LaTeX doesn't support
+ ;; them inside.
+ (org-latex--delayed-footnotes-definitions def info))))))))
;;;; Headline
@@ -1807,7 +1936,8 @@ holding contextual information."
(format "\\begin{%s}\n" (if numberedp 'enumerate 'itemize)))
;; Itemize headline
"\\item"
- (and full-text (org-string-match-p "\\`[ \t]*\\[" full-text)
+ (and full-text
+ (string-match-p "\\`[ \t]*\\[" full-text)
"\\relax")
" " full-text "\n"
headline-label
@@ -1844,8 +1974,8 @@ holding contextual information."
(lambda (k)
(and (equal (org-element-property :key k) "TOC")
(let ((v (org-element-property :value k)))
- (and (org-string-match-p "\\<headlines\\>" v)
- (org-string-match-p "\\<local\\>" v)
+ (and (string-match-p "\\<headlines\\>" v)
+ (string-match-p "\\<local\\>" v)
(format "\\stopcontents[level-%d]" level)))))
info t)))))
(if (and opt-title
@@ -1865,7 +1995,7 @@ holding contextual information."
(concat headline-label pre-blanks contents))))))))
(defun org-latex-format-headline-default-function
- (todo todo-type priority text tags info)
+ (todo _todo-type priority text tags info)
"Default format function for a headline.
See `org-latex-format-headline-function' for details."
(concat
@@ -1880,7 +2010,7 @@ See `org-latex-format-headline-function' for details."
;;;; Horizontal Rule
-(defun org-latex-horizontal-rule (horizontal-rule contents info)
+(defun org-latex-horizontal-rule (horizontal-rule _contents info)
"Transcode an HORIZONTAL-RULE object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(let ((attr (org-export-read-attribute :attr_latex horizontal-rule))
@@ -1902,13 +2032,13 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Inline Src Block
-(defun org-latex-inline-src-block (inline-src-block contents info)
+(defun org-latex-inline-src-block (inline-src-block _contents info)
"Transcode an INLINE-SRC-BLOCK element from Org to LaTeX.
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
(let* ((code (org-element-property :value inline-src-block))
(separator (org-latex--find-verb-separator code)))
- (case (plist-get info :latex-listings)
+ (cl-case (plist-get info :latex-listings)
;; Do not use a special package: transcode it verbatim.
((nil) (format "\\texttt{%s}" (org-latex--protect-text code)))
;; Use minted package.
@@ -1919,10 +2049,10 @@ contextual information."
(downcase org-lang)))
(options (org-latex--make-option-string
(plist-get info :latex-minted-options))))
- (concat (format "\\mint%s{%s}"
- (if (string= options "") "" (format "[%s]" options))
- mint-lang)
- separator code separator)))
+ (format "\\mintinline%s{%s}{%s}"
+ (if (string= options "") "" (format "[%s]" options))
+ mint-lang
+ code)))
;; Use listings package.
(otherwise
;; Maybe translate language's name.
@@ -1957,7 +2087,7 @@ holding contextual information."
todo todo-type priority title tags contents info)))
(defun org-latex-format-inlinetask-default-function
- (todo todo-type priority title tags contents info)
+ (todo _todo-type priority title tags contents info)
"Default format function for a inlinetasks.
See `org-latex-format-inlinetask-function' for details."
(let ((full-title
@@ -1982,7 +2112,7 @@ See `org-latex-format-inlinetask-function' for details."
;;;; Italic
-(defun org-latex-italic (italic contents info)
+(defun org-latex-italic (_italic contents info)
"Transcode ITALIC from Org to LaTeX.
CONTENTS is the text with italic markup. INFO is a plist holding
contextual information."
@@ -2007,14 +2137,14 @@ contextual information."
(when (and (eq (org-element-type parent) 'plain-list)
(eq (org-element-property :type parent)
'ordered))
- (incf level)))
+ (cl-incf level)))
level)))
(and count
(< level 5)
(format "\\setcounter{enum%s}{%s}\n"
(nth (1- level) '("i" "ii" "iii" "iv"))
(1- count)))))
- (checkbox (case (org-element-property :checkbox item)
+ (checkbox (cl-case (org-element-property :checkbox item)
(on "$\\boxtimes$ ")
(off "$\\square$ ")
(trans "$\\boxminus$ ")))
@@ -2033,7 +2163,7 @@ contextual information."
;; unless the brackets comes from an initial export
;; snippet (i.e. it is inserted willingly by the user).
((and contents
- (org-string-match-p "\\`[ \t]*\\[" contents)
+ (string-match-p "\\`[ \t]*\\[" contents)
(not (let ((e (car (org-element-contents item))))
(and (eq (org-element-type e) 'paragraph)
(let ((o (car (org-element-contents e))))
@@ -2054,7 +2184,7 @@ contextual information."
;;;; Keyword
-(defun org-latex-keyword (keyword contents info)
+(defun org-latex-keyword (keyword _contents info)
"Transcode a KEYWORD element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(let ((key (org-element-property :key keyword))
@@ -2065,8 +2195,8 @@ CONTENTS is nil. INFO is a plist holding contextual information."
((string= key "TOC")
(let ((case-fold-search t))
(cond
- ((org-string-match-p "\\<headlines\\>" value)
- (let* ((localp (org-string-match-p "\\<local\\>" value))
+ ((string-match-p "\\<headlines\\>" value)
+ (let* ((localp (string-match-p "\\<local\\>" value))
(parent (org-element-lineage keyword '(headline)))
(level (if (not (and localp parent)) 0
(org-export-get-relative-level parent info)))
@@ -2082,9 +2212,9 @@ CONTENTS is nil. INFO is a plist holding contextual information."
\\printcontents[level-%d]{}{0}{%s}"
level level (or depth ""))
(concat depth (and depth "\n") "\\tableofcontents"))))
- ((org-string-match-p "\\<tables\\>" value) "\\listoftables")
- ((org-string-match-p "\\<listings\\>" value)
- (case (plist-get info :latex-listings)
+ ((string-match-p "\\<tables\\>" value) "\\listoftables")
+ ((string-match-p "\\<listings\\>" value)
+ (cl-case (plist-get info :latex-listings)
((nil) "\\listoffigures")
(minted "\\listoflistings")
(otherwise "\\lstlistoflistings")))))))))
@@ -2092,7 +2222,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Latex Environment
-(defun org-latex-latex-environment (latex-environment contents info)
+(defun org-latex-latex-environment (latex-environment _contents info)
"Transcode a LATEX-ENVIRONMENT element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(when (plist-get info :with-latex)
@@ -2112,22 +2242,20 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Latex Fragment
-(defun org-latex-latex-fragment (latex-fragment contents info)
+(defun org-latex-latex-fragment (latex-fragment _contents _info)
"Transcode a LATEX-FRAGMENT object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(let ((value (org-element-property :value latex-fragment)))
;; Trim math markers since the fragment is enclosed within
;; a latex-math-block object anyway.
- (cond ((string-match "\\`\\(\\$\\{1,2\\}\\)\\([^\000]*\\)\\1\\'" value)
- (match-string 2 value))
- ((string-match "\\`\\\\(\\([^\000]*\\)\\\\)\\'" value)
- (match-string 1 value))
+ (cond ((string-match-p "\\`\\$[^$]" value) (substring value 1 -1))
+ ((string-prefix-p "\\(" value) (substring value 2 -2))
(t value))))
;;;; Line Break
-(defun org-latex-line-break (line-break contents info)
+(defun org-latex-line-break (_line-break _contents _info)
"Transcode a LINE-BREAK object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
"\\\\\n")
@@ -2152,13 +2280,12 @@ used as a communication channel."
(cond ((string= float "wrap") 'wrap)
((string= float "sideways") 'sideways)
((string= float "multicolumn") 'multicolumn)
+ ((and (plist-member attr :float) (not float)) 'nonfloat)
((or float
(org-element-property :caption parent)
(org-string-nw-p (plist-get attr :caption)))
- (if (and (plist-member attr :float) (not float))
- 'nonfloat
- 'figure))
- ((and (not float) (plist-member attr :float)) nil))))
+ 'figure)
+ (t 'nonfloat))))
(placement
(let ((place (plist-get attr :placement)))
(cond
@@ -2167,6 +2294,9 @@ used as a communication channel."
((eq float 'figure)
(format "[%s]" (plist-get info :latex-default-figure-position)))
(t ""))))
+ (center
+ (if (plist-member attr :center) (plist-get attr :center)
+ (plist-get info :latex-images-centered)))
(comment-include (if (plist-get attr :comment-include) "%" ""))
;; It is possible to specify width and height in the
;; ATTR_LATEX line, and also via default variables.
@@ -2211,14 +2341,14 @@ used as a communication channel."
(let ((search-option (org-element-property :search-option link)))
(when (and search-option
(equal filetype "pdf")
- (org-string-match-p "\\`[0-9]+\\'" search-option)
- (not (org-string-match-p "page=" options)))
+ (string-match-p "\\`[0-9]+\\'" search-option)
+ (not (string-match-p "page=" options)))
(setq options (concat options ",page=" search-option))))
(setq image-code
(format "\\includegraphics%s{%s}"
(cond ((not (org-string-nw-p options)) "")
- ((= (aref options 0) ?,)
- (format "[%s]"(substring options 1)))
+ ((string-prefix-p "," options)
+ (format "[%s]" (substring options 1)))
(t (format "[%s]" options)))
path))
(when (equal filetype "svg")
@@ -2231,46 +2361,53 @@ used as a communication channel."
image-code
nil t))))
;; Return proper string, depending on FLOAT.
- (case float
- (wrap (format "\\begin{wrapfigure}%s
-%s\\centering
+ (pcase float
+ (`wrap (format "\\begin{wrapfigure}%s
+%s%s
%s%s
%s\\end{wrapfigure}"
- placement
- (if caption-above-p caption "")
- comment-include image-code
- (if caption-above-p "" caption)))
- (sideways (format "\\begin{sidewaysfigure}
-%s\\centering
+ placement
+ (if caption-above-p caption "")
+ (if center "\\centering" "")
+ comment-include image-code
+ (if caption-above-p "" caption)))
+ (`sideways (format "\\begin{sidewaysfigure}
+%s%s
%s%s
%s\\end{sidewaysfigure}"
- (if caption-above-p caption "")
- comment-include image-code
- (if caption-above-p "" caption)))
- (multicolumn (format "\\begin{figure*}%s
-%s\\centering
+ (if caption-above-p caption "")
+ (if center "\\centering" "")
+ comment-include image-code
+ (if caption-above-p "" caption)))
+ (`multicolumn (format "\\begin{figure*}%s
+%s%s
%s%s
%s\\end{figure*}"
- placement
- (if caption-above-p caption "")
- comment-include image-code
- (if caption-above-p "" caption)))
- (figure (format "\\begin{figure}%s
-%s\\centering
+ placement
+ (if caption-above-p caption "")
+ (if center "\\centering" "")
+ comment-include image-code
+ (if caption-above-p "" caption)))
+ (`figure (format "\\begin{figure}%s
+%s%s
%s%s
%s\\end{figure}"
- placement
- (if caption-above-p caption "")
- comment-include image-code
- (if caption-above-p "" caption)))
- (nonfloat
+ placement
+ (if caption-above-p caption "")
+ (if center "\\centering" "")
+ comment-include image-code
+ (if caption-above-p "" caption)))
+ ((guard center)
(format "\\begin{center}
%s%s
%s\\end{center}"
(if caption-above-p caption "")
image-code
(if caption-above-p "" caption)))
- (otherwise image-code))))
+ (_
+ (concat (if caption-above-p caption "")
+ image-code
+ (if caption-above-p caption ""))))))
(defun org-latex-link (link desc info)
"Transcode a LINK object from Org to LaTeX.
@@ -2309,7 +2446,7 @@ INFO is a plist holding contextual information. See
(let ((destination (if (string= type "fuzzy")
(org-export-resolve-fuzzy-link link info)
(org-export-resolve-id-link link info))))
- (case (org-element-type destination)
+ (cl-case (org-element-type destination)
;; Id link points to an external file.
(plain-text
(if desc (format "\\href{%s}{%s}" destination desc)
@@ -2353,7 +2490,7 @@ INFO is a plist holding contextual information. See
;;;; Node Property
-(defun org-latex-node-property (node-property contents info)
+(defun org-latex-node-property (node-property _contents _info)
"Transcode a NODE-PROPERTY element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
@@ -2365,7 +2502,7 @@ information."
;;;; Paragraph
-(defun org-latex-paragraph (paragraph contents info)
+(defun org-latex-paragraph (_paragraph contents _info)
"Transcode a PARAGRAPH element from Org to LaTeX.
CONTENTS is the contents of the paragraph, as a string. INFO is
the plist used as a communication channel."
@@ -2413,7 +2550,7 @@ contextual information."
(replace-regexp-in-string
(concat "[%$#&{}_~^]\\|\\\\" (and specialp "\\([^-]\\|$\\)"))
(lambda (m)
- (case (string-to-char m)
+ (cl-case (string-to-char m)
(?\\ "$\\\\backslash$\\1")
(?~ "\\\\textasciitilde{}")
(?^ "\\\\^{}")
@@ -2436,7 +2573,7 @@ contextual information."
;;;; Planning
-(defun org-latex-planning (planning contents info)
+(defun org-latex-planning (planning _contents info)
"Transcode a PLANNING element from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
@@ -2470,7 +2607,7 @@ information."
;;;; Property Drawer
-(defun org-latex-property-drawer (property-drawer contents info)
+(defun org-latex-property-drawer (_property-drawer contents _info)
"Transcode a PROPERTY-DRAWER element from Org to LaTeX.
CONTENTS holds the contents of the drawer. INFO is a plist
holding contextual information."
@@ -2524,24 +2661,28 @@ it."
(org-element-extract-element previous)
(org-element-adopt-elements matrices previous)
(setq previous next))
+ ;; Inherit `:post-blank' from the value of the last
+ ;; swallowed table. Set the latter's `:post-blank'
+ ;; value to 0 so as to not duplicate empty lines.
(org-element-put-property
matrices :post-blank (org-element-property :post-blank previous))
+ (org-element-put-property previous :post-blank 0)
(org-element-extract-element previous)
(org-element-adopt-elements matrices previous))))))
info)
data)
-(defun org-latex-matrices (matrices contents info)
+(defun org-latex-matrices (matrices contents _info)
"Transcode a MATRICES element from Org to LaTeX.
CONTENTS is a string. INFO is a plist used as a communication
channel."
- (format (case (org-element-property :markup matrices)
+ (format (cl-case (org-element-property :markup matrices)
(inline "\\(%s\\)")
(equation "\\begin{equation}\n%s\\end{equation}")
(t "\\[\n%s\\]"))
contents))
-(defun org-latex-matrices-tree-filter (tree backend info)
+(defun org-latex-matrices-tree-filter (tree _backend info)
(org-latex--wrap-latex-matrices tree info))
;;;; Pseudo Object: LaTeX Math Block
@@ -2554,16 +2695,15 @@ channel."
DATA is a parse tree or a secondary string. INFO is a plist
containing export options. Modify DATA by side-effect and return it."
(let ((valid-object-p
- (function
- ;; Non-nil when OBJ can be added to the latex math block.
- (lambda (obj)
- (case (org-element-type obj)
- (entity (org-element-property :latex-math-p obj))
- (latex-fragment
- (let ((value (org-element-property :value obj)))
- (or (org-string-match-p "\\`\\\\([^\000]*\\\\)\\'" value)
- (org-string-match-p "\\`\\$[^\000]*\\$\\'" value))))
- ((subscript superscript) t))))))
+ ;; Non-nil when OBJ can be added to the latex math block.
+ (lambda (obj)
+ (pcase (org-element-type obj)
+ (`entity (org-element-property :latex-math-p obj))
+ (`latex-fragment
+ (let ((value (org-element-property :value obj)))
+ (or (string-prefix-p "\\(" value)
+ (string-match-p "\\`\\$[^$]" value))))
+ ((or `subscript `superscript) t)))))
(org-element-map data '(entity latex-fragment subscript superscript)
(lambda (object)
;; Skip objects already wrapped.
@@ -2598,15 +2738,15 @@ containing export options. Modify DATA by side-effect and return it."
;; Return updated DATA.
data))
-(defun org-latex-math-block-tree-filter (tree backend info)
+(defun org-latex-math-block-tree-filter (tree _backend info)
(org-latex--wrap-latex-math-block tree info))
-(defun org-latex-math-block-options-filter (info backend)
+(defun org-latex-math-block-options-filter (info _backend)
(dolist (prop '(:author :date :title) info)
(plist-put info prop
(org-latex--wrap-latex-math-block (plist-get info prop) info))))
-(defun org-latex-math-block (math-block contents info)
+(defun org-latex-math-block (_math-block contents _info)
"Transcode a MATH-BLOCK object from Org to LaTeX.
CONTENTS is a string. INFO is a plist used as a communication
channel."
@@ -2634,7 +2774,7 @@ contextual information."
;;;; Section
-(defun org-latex-section (section contents info)
+(defun org-latex-section (_section contents _info)
"Transcode a SECTION element from Org to LaTeX.
CONTENTS holds the contents of the section. INFO is a plist
holding contextual information."
@@ -2660,7 +2800,7 @@ holding contextual information."
;;;; Src Block
-(defun org-latex-src-block (src-block contents info)
+(defun org-latex-src-block (src-block _contents info)
"Transcode a SRC-BLOCK element from Org to LaTeX.
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
@@ -2672,9 +2812,7 @@ contextual information."
(custom-env (and lang
(cadr (assq (intern lang)
org-latex-custom-lang-environments))))
- (num-start (case (org-element-property :number-lines src-block)
- (continued (org-export-get-loc src-block info))
- (new 0)))
+ (num-start (org-export-get-loc src-block info))
(retain-labels (org-element-property :retain-labels src-block))
(attributes (org-export-read-attribute :attr_latex src-block))
(float (plist-get attributes :float))
@@ -2700,13 +2838,21 @@ contextual information."
(org-export-format-code-default src-block info))))))
;; Case 2. Custom environment.
(custom-env
- (let ((caption-str (org-latex--caption/label-string src-block info)))
- (format "\\begin{%s}\n%s\\end{%s}\n"
- custom-env
- (concat (and caption-above-p caption-str)
- (org-export-format-code-default src-block info)
- (and (not caption-above-p) caption-str))
- custom-env)))
+ (let ((caption-str (org-latex--caption/label-string src-block info))
+ (formatted-src (org-export-format-code-default src-block info)))
+ (if (string-match-p "\\`[a-zA-Z0-9]+\\'" custom-env)
+ (format "\\begin{%s}\n%s\\end{%s}\n"
+ custom-env
+ (concat (and caption-above-p caption-str)
+ formatted-src
+ (and (not caption-above-p) caption-str))
+ custom-env)
+ (format-spec custom-env
+ `((?s . ,formatted-src)
+ (?c . ,caption)
+ (?f . ,float)
+ (?l . ,(org-latex--label src-block info))
+ (?o . ,(or (plist-get attributes :options) "")))))))
;; Case 3. Use minted package.
((eq listings 'minted)
(let* ((caption-str (org-latex--caption/label-string src-block info))
@@ -2749,7 +2895,7 @@ contextual information."
"\n")))))
(org-export-format-code
(car code-info)
- (lambda (loc num ref)
+ (lambda (loc _num ref)
(concat
loc
(when ref
@@ -2792,7 +2938,9 @@ contextual information."
((and float (not (assoc "float" lst-opt)))
`(("float" ,(plist-get info :latex-default-figure-position)))))
`(("language" ,lst-lang))
- (if label `(("label" ,label)) '(("label" " ")))
+ (if label
+ `(("label" ,(org-latex--label src-block info)))
+ '(("label" " ")))
(if caption-str `(("caption" ,caption-str)) '(("caption" " ")))
`(("captionpos" ,(if caption-above-p "t" "b")))
(cond ((assoc "numbers" lst-opt) nil)
@@ -2811,21 +2959,21 @@ contextual information."
(org-split-string (car code-info) "\n")))))
(org-export-format-code
(car code-info)
- (lambda (loc num ref)
+ (lambda (loc _num ref)
(concat
loc
(when ref
;; Ensure references are flushed to the right,
;; separated with 6 spaces from the widest line of
;; code
- (concat (make-string (+ (- max-width (length loc)) 6) ? )
+ (concat (make-string (+ (- max-width (length loc)) 6) ?\s)
(format "(%s)" ref)))))
nil (and retain-labels (cdr code-info))))))))))))
;;;; Statistics Cookie
-(defun org-latex-statistics-cookie (statistics-cookie contents info)
+(defun org-latex-statistics-cookie (statistics-cookie _contents _info)
"Transcode a STATISTICS-COOKIE object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
(replace-regexp-in-string
@@ -2834,7 +2982,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
;;;; Strike-Through
-(defun org-latex-strike-through (strike-through contents info)
+(defun org-latex-strike-through (_strike-through contents info)
"Transcode STRIKE-THROUGH from Org to LaTeX.
CONTENTS is the text with strike-through markup. INFO is a plist
holding contextual information."
@@ -2847,12 +2995,11 @@ holding contextual information."
"Transcode a subscript or superscript object.
OBJECT is an Org object. INFO is a plist used as a communication
channel."
- (let ((type (org-element-type object))
- (output ""))
+ (let ((output ""))
(org-element-map (org-element-contents object)
(cons 'plain-text org-element-all-objects)
(lambda (obj)
- (case (org-element-type obj)
+ (cl-case (org-element-type obj)
((entity latex-fragment)
(let ((data (org-trim (org-export-data obj info))))
(string-match
@@ -2880,7 +3027,7 @@ channel."
output
(and (> (length output) 1) "}"))))
-(defun org-latex-subscript (subscript contents info)
+(defun org-latex-subscript (subscript _contents info)
"Transcode a SUBSCRIPT object from Org to LaTeX.
CONTENTS is the contents of the object. INFO is a plist holding
contextual information."
@@ -2889,7 +3036,7 @@ contextual information."
;;;; Superscript
-(defun org-latex-superscript (superscript contents info)
+(defun org-latex-superscript (superscript _contents info)
"Transcode a SUPERSCRIPT object from Org to LaTeX.
CONTENTS is the contents of the object. INFO is a plist holding
contextual information."
@@ -2951,7 +3098,7 @@ a communication channel."
;; Check left border for the first cell only.
(when (and (memq 'left borders) (not align))
(push "|" align))
- (push (case (org-export-table-cell-alignment cell info)
+ (push (cl-case (org-export-table-cell-alignment cell info)
(left "l")
(right "r")
(center "c"))
@@ -3103,7 +3250,7 @@ property."
(let ((n 0) (pos 0))
(while (and (< (length output) pos)
(setq pos (string-match "^\\\\hline\n?" output pos)))
- (incf n)
+ (cl-incf n)
(unless (= n 2) (setq output (replace-match "" nil nil output))))))
(let ((centerp (if (plist-member attr :center) (plist-get attr :center)
(plist-get info :latex-tables-centered))))
@@ -3239,7 +3386,7 @@ a communication channel."
;;;; Target
-(defun org-latex-target (target contents info)
+(defun org-latex-target (target _contents info)
"Transcode a TARGET object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
@@ -3248,14 +3395,14 @@ information."
;;;; Timestamp
-(defun org-latex-timestamp (timestamp contents info)
+(defun org-latex-timestamp (timestamp _contents info)
"Transcode a TIMESTAMP object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual
information."
(let ((value (org-latex-plain-text (org-timestamp-translate timestamp) info)))
(format
(plist-get info
- (case (org-element-property :type timestamp)
+ (cl-case (org-element-property :type timestamp)
((active active-range) :latex-active-timestamp-format)
((inactive inactive-range) :latex-inactive-timestamp-format)
(otherwise :latex-diary-timestamp-format)))
@@ -3264,7 +3411,7 @@ information."
;;;; Underline
-(defun org-latex-underline (underline contents info)
+(defun org-latex-underline (_underline contents info)
"Transcode UNDERLINE from Org to LaTeX.
CONTENTS is the text with underline markup. INFO is a plist
holding contextual information."
@@ -3273,7 +3420,7 @@ holding contextual information."
;;;; Verbatim
-(defun org-latex-verbatim (verbatim contents info)
+(defun org-latex-verbatim (verbatim _contents info)
"Transcode a VERBATIM object from Org to LaTeX.
CONTENTS is nil. INFO is a plist used as a communication
channel."
@@ -3344,9 +3491,9 @@ is non-nil."
;;;###autoload
(defun org-latex-convert-region-to-latex ()
- "Assume the current region has org-mode syntax, and convert it to LaTeX.
+ "Assume the current region has Org syntax, and convert it to LaTeX.
This can be used in any buffer. For example, you can write an
-itemized list in org-mode syntax in an LaTeX buffer and use this
+itemized list in Org syntax in an LaTeX buffer and use this
command to convert it."
(interactive)
(org-export-replace-region-by 'latex))
@@ -3422,74 +3569,59 @@ Return PDF file's name."
"Compile a TeX file.
TEXFILE is the name of the file being compiled. Processing is
-done through the command specified in `org-latex-pdf-process'.
+done through the command specified in `org-latex-pdf-process',
+which see. Output is redirected to \"*Org PDF LaTeX Output*\"
+buffer.
When optional argument SNIPPET is non-nil, TEXFILE is a temporary
file used to preview a LaTeX snippet. In this case, do not
-create a log buffer and do not bother removing log files.
-
-Return PDF file name or an error if it couldn't be produced."
- (let* ((base-name (file-name-sans-extension (file-name-nondirectory texfile)))
- (full-name (file-truename texfile))
- (out-dir (file-name-directory texfile))
- ;; Properly set working directory for compilation.
- (default-directory (if (file-name-absolute-p texfile)
- (file-name-directory full-name)
- default-directory))
- (time (current-time))
- warnings)
- (unless snippet (message "Processing LaTeX file %s..." texfile))
- (save-window-excursion
- (cond
- ;; A function is provided: Apply it.
- ((functionp org-latex-pdf-process)
- (funcall org-latex-pdf-process (shell-quote-argument texfile)))
- ;; A list is provided: Replace %b, %f and %o with appropriate
- ;; values in each command before applying it. Output is
- ;; redirected to "*Org PDF LaTeX Output*" buffer.
- ((consp org-latex-pdf-process)
- (let ((outbuf (and (not snippet)
- (get-buffer-create "*Org PDF LaTeX Output*"))))
- (dolist (command org-latex-pdf-process)
- (shell-command
- (replace-regexp-in-string
- "%b" (shell-quote-argument base-name)
- (replace-regexp-in-string
- "%f" (shell-quote-argument full-name)
- (replace-regexp-in-string
- "%o" (shell-quote-argument out-dir) command t t) t t) t t)
- outbuf))
- ;; Collect standard errors from output buffer.
- (setq warnings (and (not snippet)
- (org-latex--collect-warnings outbuf)))))
- (t (error "No valid command to process to PDF")))
- (let ((pdffile (concat out-dir base-name ".pdf")))
- ;; Check for process failure. Provide collected errors if
- ;; possible.
- (if (or (not (file-exists-p pdffile))
- ;; Only compare times up to whole seconds as some filesystems
- ;; (e.g. HFS+) do not retain any finer granularity.
- (time-less-p (org-sublist (nth 5 (file-attributes pdffile)) 1 2)
- (org-sublist time 1 2)))
- (error (format "PDF file %s wasn't produced" pdffile))
- ;; Else remove log files, when specified, and signal end of
- ;; process to user, along with any error encountered.
- (unless snippet
- (when org-latex-remove-logfiles
- (dolist (file (directory-files
- out-dir t
- (concat (regexp-quote base-name)
- "\\(?:\\.[0-9]+\\)?"
- "\\."
- (regexp-opt org-latex-logfiles-extensions))))
- (delete-file file)))
- (message (concat "PDF file produced"
- (cond
- ((eq warnings 'error) " with errors.")
- (warnings (concat " with warnings: " warnings))
- (t "."))))))
- ;; Return output file name.
- pdffile))))
+create a log buffer and do not remove log files.
+
+Return PDF file name or raise an error if it couldn't be
+produced."
+ (unless snippet (message "Processing LaTeX file %s..." texfile))
+ (let* ((compiler
+ (or (with-temp-buffer
+ (save-excursion (insert-file-contents texfile))
+ (and (search-forward-regexp (regexp-opt org-latex-compilers)
+ (line-end-position 2)
+ t)
+ (progn (beginning-of-line) (looking-at-p "%"))
+ (match-string 0)))
+ "pdflatex"))
+ (process (if (functionp org-latex-pdf-process) org-latex-pdf-process
+ ;; Replace "%latex" and "%bibtex" with,
+ ;; respectively, "%L" and "%B" so as to adhere to
+ ;; `format-spec' specifications.
+ (mapcar (lambda (command)
+ (replace-regexp-in-string
+ "%\\(?:bib\\|la\\)tex\\>"
+ (lambda (m) (upcase (substring m 0 2)))
+ command))
+ org-latex-pdf-process)))
+ (spec `((?B . ,(shell-quote-argument org-latex-bib-compiler))
+ (?L . ,(shell-quote-argument compiler))))
+ (log-buf-name "*Org PDF LaTeX Output*")
+ (log-buf (and (not snippet) (get-buffer-create log-buf-name)))
+ (outfile (org-compile-file texfile process "pdf"
+ (format "See %S for details" log-buf-name)
+ log-buf spec)))
+ (unless snippet
+ (when org-latex-remove-logfiles
+ (mapc #'delete-file
+ (directory-files
+ (file-name-directory texfile) t
+ (concat (regexp-quote (file-name-base outfile))
+ "\\(?:\\.[0-9]+\\)?\\."
+ (regexp-opt org-latex-logfiles-extensions)))))
+ (let ((warnings (org-latex--collect-warnings log-buf)))
+ (message (concat "PDF file produced"
+ (cond
+ ((eq warnings 'error) " with errors.")
+ (warnings (concat " with warnings: " warnings))
+ (t "."))))))
+ ;; Return output file name.
+ outfile))
(defun org-latex--collect-warnings (buffer)
"Collect some warnings from \"pdflatex\" command output.