]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-latex.el
Merge from emacs-23
[gnu-emacs] / lisp / org / org-latex.el
index 55444c08bbe44dd052112e58b46627320a29b516..7f07052ee54cfd657d2b19cd80f75f37dfbfcf4b 100644 (file)
@@ -1,10 +1,10 @@
 ;;; org-latex.el --- LaTeX exporter for org-mode
 ;;
-;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 ;;
 ;; Emacs Lisp Archive Entry
 ;; Filename: org-latex.el
-;; Version: 7.01
+;; Version: 7.4
 ;; Author: Bastien Guerry <bzg AT altern DOT org>
 ;; Maintainer: Carsten Dominik <carsten.dominik AT gmail DOT com>
 ;; Keywords: org, wp, tex
@@ -280,6 +280,11 @@ markup defined, the first one in the association list will be used."
                   (string :tag "Keyword")
                   (string :tag "Markup")))))
 
+(defcustom org-export-latex-tag-markup "\\textbf{%s}"
+  "Markup for tags, as a printf format."
+  :group 'org-export-latex
+  :type 'string)
+
 (defcustom org-export-latex-timestamp-markup "\\textit{%s}"
   "A printf format string to be applied to time stamps."
   :group 'org-export-latex
@@ -290,7 +295,14 @@ markup defined, the first one in the association list will be used."
   :group 'org-export-latex
   :type 'string)
 
-(defcustom org-export-latex-hyperref-format "\\href{%s}{%s}"
+(defcustom org-export-latex-href-format "\\href{%s}{%s}"
+  "A printf format string to be applied to href links.
+The format must contain two %s instances.  The first will be filled with
+the link, the second with the link description."
+  :group 'org-export-latex
+  :type 'string)
+
+(defcustom org-export-latex-hyperref-format "\\hyperref[%s]{%s}"
   "A printf format string to be applied to hyperref links.
 The format must contain two %s instances.  The first will be filled with
 the link, the second with the link description."
@@ -371,12 +383,30 @@ for example using customize, or with something like
 
   (require 'org-latex)
   (add-to-list 'org-export-latex-packages-alist '(\"\" \"listings\"))
-  (add-to-list 'org-export-latex-packages-alist '(\"\" \"color\"))"
+  (add-to-list 'org-export-latex-packages-alist '(\"\" \"color\"))
+
+Alternatively,
+
+  (setq org-export-latex-listings 'minted)
+
+causes source code to be exported using the minted package as
+opposed to listings. If you want to use minted, you need to add
+the minted package to `org-export-latex-packages-alist', for
+example using customize, or with
+
+  (require 'org-latex)
+  (add-to-list 'org-export-latex-packages-alist '(\"\" \"minted\"))
+
+In addition, it is neccessary to install
+pygments (http://pygments.org), and to configure
+`org-latex-to-pdf-process' so that the -shell-escape option is
+passed to pdflatex.
+"
   :group 'org-export-latex
   :type 'boolean)
 
 (defcustom org-export-latex-listings-langs
-  '((emacs-lisp "Lisp") (lisp "Lisp")
+  '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp")
     (c "C") (cc "C++")
     (fortran "fortran")
     (perl "Perl") (cperl "Perl") (python "Python") (ruby "Ruby")
@@ -398,6 +428,38 @@ hurt if it is present."
           (symbol :tag "Major mode       ")
           (string :tag "Listings language"))))
 
+(defcustom org-export-latex-listings-w-names t
+  "Non-nil means export names of named code blocks.
+Code blocks exported with the listings package (controlled by the
+`org-export-latex-listings' variable) can be named in the style
+of noweb."
+  :group 'org-export-latex
+  :type 'boolean)
+
+(defcustom org-export-latex-minted-langs
+  '((emacs-lisp "common-lisp")
+    (cc "c++")
+    (cperl "perl")
+    (shell-script "bash")
+    (caml "ocaml"))
+  "Alist mapping languages to their minted 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 parameter
+for the minted package.  If the mode name and the listings name are
+the same, the language does not need an entry in this list - but it does not
+hurt if it is present.
+
+Note that minted uses all lower case for language identifiers,
+and that the full list of language identifiers can be obtained
+with:
+pygmentize -L lexers
+"
+  :group 'org-export-latex
+  :type '(repeat
+         (list
+          (symbol :tag "Major mode       ")
+          (string :tag "Listings language"))))
+
 (defcustom org-export-latex-remove-from-headlines
   '(:todo nil :priority nil :tags nil)
   "A plist of keywords to remove from headlines.  OBSOLETE.
@@ -443,24 +505,53 @@ allowed.  The default we use here encompasses both."
   :group 'org-export)
 
 (defcustom org-latex-to-pdf-process
-  '("pdflatex -interaction nonstopmode %s"
-    "pdflatex -interaction nonstopmode %s")
+  '("pdflatex -interaction nonstopmode -output-directory %o %f"
+    "pdflatex -interaction nonstopmode -output-directory %o %f"
+    "pdflatex -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.  %s in the command will be replaced by the full file name, %b
-by the file base name (i.e. without extension).
+as a command.  %f in the command will be replaced by the full file name, %b
+by the file base name (i.e. without extension) and %o by the base directory
+of the file.
+
 The reason why this is a list is that it usually takes several runs of
-pdflatex, maybe mixed with a call to bibtex.  Org does not have a clever
+`pdflatex', maybe mixed with a call to `bibtex'.  Org 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.  Org does offer it as one
+of the customize options.
+
 Alternatively, this may be a Lisp function that does the processing, so you
 could use this to apply the machinery of AUCTeX or the Emacs LaTeX mode.
 This function should accept the file name as its single argument."
   :group 'org-export-pdf
-  :type '(choice (repeat :tag "Shell command sequence"
+  :type '(choice
+         (repeat :tag "Shell command sequence"
                  (string :tag "Shell command"))
-                (function)))
+         (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 "texi2dvi"
+                ("texi2dvi -p -b -c -V %f"))
+         (const :tag "rubber"
+                ("rubber -d --into %o %f"))
+         (function)))
 
 (defcustom org-export-pdf-logfiles
   '("aux" "idx" "log" "out" "toc" "nav" "snm" "vrb")
@@ -832,9 +923,10 @@ when PUB-DIR is set, use this as the publishing directory."
                     (save-excursion
                       (goto-char (point-min))
                       (re-search-forward "\\\\bibliography{" nil t))))
-        cmd)
+        cmd output-dir errors)
     (with-current-buffer outbuf (erase-buffer))
-    (message "Processing LaTeX file...")
+    (message (concat "Processing LaTeX file " file "..."))
+    (setq output-dir (file-name-directory file))
     (if (and cmds (symbolp cmds))
        (funcall cmds (shell-quote-argument file))
       (while cmds
@@ -844,23 +936,52 @@ when PUB-DIR is set, use this as the publishing directory."
                     (save-match-data
                       (shell-quote-argument base))
                     t t cmd)))
-       (while (string-match "%s" cmd)
+       (while (string-match "%f" cmd)
          (setq cmd (replace-match
                     (save-match-data
                       (shell-quote-argument file))
                     t t cmd)))
-       (shell-command cmd outbuf outbuf)))
-    (message "Processing LaTeX file...done")
+       (while (string-match "%o" cmd)
+         (setq cmd (replace-match
+                    (save-match-data
+                      (shell-quote-argument output-dir))
+                    t t cmd)))
+       (shell-command cmd outbuf)))
+    (message (concat "Processing LaTeX file " file "...done"))
+    (setq errors (org-export-latex-get-error outbuf))
     (if (not (file-exists-p pdffile))
-       (error "PDF file was not produced")
+       (error (concat "PDF file " pdffile " was not produced"
+                      (if errors (concat ":" errors "") "")))
       (set-window-configuration wconfig)
       (when org-export-pdf-remove-logfiles
        (dolist (ext org-export-pdf-logfiles)
          (setq file (concat base "." ext))
          (and (file-exists-p file) (delete-file file))))
-      (message "Exporting to PDF...done")
+      (message (concat
+               "Exporting to PDF...done"
+               (if errors
+                   (concat ", with some errors:" errors)
+                 "")))
       pdffile)))
 
+(defun org-export-latex-get-error (buf)
+  "Collect the kinds of errors that remain in pdflatex processing."
+  (with-current-buffer buf
+    (save-excursion
+      (goto-char (point-max))
+      (when (re-search-backward "^[ \t]*This is pdf.*?TeX.*?Version" nil t)
+       ;; OK, we are at the location of the final run
+       (let ((pos (point)) (errors "") (case-fold-search t))
+         (if (re-search-forward "Reference.*?undefined" nil t)
+             (setq errors (concat errors " [undefined reference]")))
+         (goto-char pos)
+         (if (re-search-forward "Citation.*?undefined" nil t)
+             (setq errors (concat errors " [undefined citation]")))
+         (goto-char pos)
+         (if (re-search-forward "Undefined control sequence" nil t)
+             (setq errors (concat errors " [undefined control sequence]")))
+         (and (org-string-nw-p errors) errors))))))
+
 ;;;###autoload
 (defun org-export-as-pdf-and-open (arg)
   "Export as LaTeX, then process through to PDF, and open."
@@ -1158,14 +1279,15 @@ OPT-PLIST is the options plist for current buffer."
        (plist-get opt-plist :latex-header-extra)))
      ;; append another special variable
      (org-export-apply-macros-in-string org-export-latex-append-header)
-     ;; define align if not yet defined
+     ;; define alert if not yet defined
      "\n\\providecommand{\\alert}[1]{\\textbf{#1}}"
+     ;; beginning of the document
+     "\n\\begin{document}\n\n"
      ;; insert the title
      (format
       "\n\n\\title{%s}\n"
       ;; convert the title
-      (org-export-latex-content
-       title '(lists tables fixed-width keywords)))
+      (org-export-latex-fontify-headline title))
      ;; insert author info
      (if (plist-get opt-plist :author-info)
         (format "\\author{%s}\n"
@@ -1177,8 +1299,6 @@ OPT-PLIST is the options plist for current buffer."
             (format-time-string
              (or (plist-get opt-plist :date)
                  org-export-latex-date-format)))
-     ;; beginning of the document
-     "\n\\begin{document}\n\n"
      ;; insert the title command
      (when (string-match "\\S-" title)
        (if (string-match "%s" org-export-latex-title-command)
@@ -1205,7 +1325,7 @@ If END is non-nil, it is the end of the region."
   (save-excursion
     (goto-char (or beg (point-min)))
     (let* ((pt (point))
-          (end (if (re-search-forward "^\\*+ " end t)
+          (end (if (re-search-forward (org-get-limited-outline-regexp) end t)
                    (goto-char (match-beginning 0))
                  (goto-char (or end (point-max))))))
       (prog1
@@ -1227,9 +1347,13 @@ If END is non-nil, it is the end of the region."
                                '(:org-license-to-kill t))
           (save-excursion
             (goto-char pt)
-            (while (re-search-forward "^[ \t]*#+.*\n?" limit t)
-              (remove-text-properties (match-beginning 0) (match-end 0)
-                               '(:org-license-to-kill t))))))))))
+            (while (re-search-forward "^[ \t]*#\\+.*\n?" limit t)
+              (let ((case-fold-search t))
+                (unless (org-string-match-p
+                         "^[ \t]*#\\+\\(attr_\\|caption\\>\\|label\\>\\)"
+                         (match-string 0))
+                  (remove-text-properties (match-beginning 0) (match-end 0)
+                                          '(:org-license-to-kill t))))))))))))
               
 
 (defvar org-export-latex-header-defs nil
@@ -1310,13 +1434,13 @@ links, keywords, lists, tables, fixed-width"
          (replace-match "")
        (replace-match (format "\\textbf{%s}" (match-string 0)) t t)))
     ;; convert tags
-    (when (re-search-forward "\\(:[a-zA-Z0-9_@]+\\)+:" nil t)
+    (when (re-search-forward "\\(:[a-zA-Z0-9_@#%]+\\)+:" nil t)
       (if (or (not org-export-with-tags)
              (plist-get remove-list :tags))
          (replace-match "")
        (replace-match
         (org-export-latex-protect-string
-         (format "\\textbf{%s}"
+         (format org-export-latex-tag-markup
                  (save-match-data
                    (replace-regexp-in-string
                     "_" "\\\\_" (match-string 0)))))
@@ -1328,6 +1452,33 @@ links, keywords, lists, tables, fixed-width"
     ;; FIXME: org-inside-LaTeX-fragment-p doesn't work when the $...$ is at
     ;; the beginning of the buffer - inserting "\n" is safe here though.
     (insert "\n" string)
+
+    ;; Preserve math snippets
+    
+    (let* ((matchers (plist-get org-format-latex-options :matchers))
+          (re-list org-latex-regexps)
+          beg end re e m n block off)
+      ;; Check the different regular expressions
+      (while (setq e (pop re-list))
+       (setq m (car e) re (nth 1 e) n (nth 2 e)
+             block (if (nth 3 e) "\n\n" ""))
+       (setq off (if (member m '("$" "$1")) 1 0))
+       (when (and (member m matchers) (not (equal m "begin")))
+         (goto-char (point-min))
+         (while (re-search-forward re nil t)
+           (setq beg (+ (match-beginning 0) off) end (- (match-end 0) 0))
+           (add-text-properties beg end
+                                '(org-protected t org-latex-math t))))))
+
+    ;; Convert LaTeX to \LaTeX{} and TeX to \TeX{}
+    (goto-char (point-min))
+    (let ((case-fold-search nil))
+      (while (re-search-forward "\\<\\(\\(La\\)?TeX\\)\\>" nil t)
+       (unless (eq (char-before (match-beginning 1)) ?\\)
+         (org-if-unprotected-1
+          (replace-match (org-export-latex-protect-string
+                          (concat "\\" (match-string 1)
+                                  "{}")) t t)))))
     (goto-char (point-min))
     (let ((re (concat "\\\\\\([a-zA-Z]+\\)"
                      "\\(?:<[^<>\n]*>\\)*"
@@ -1589,7 +1740,7 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
              (org-table-last-column-widths (copy-sequence
                                             org-table-last-column-widths))
              fnum fields line lines olines gr colgropen line-fmt align
-             caption shortn label attr floatp longtblp)
+             caption shortn label attr floatp placement longtblp)
         (if org-export-latex-tables-verbatim
             (let* ((tbl (concat "\\begin{verbatim}\n" raw-table
                                 "\\end{verbatim}\n")))
@@ -1609,7 +1760,12 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
                   align (and attr (stringp attr)
                              (string-match "\\<align=\\([^ \t\n\r]+\\)" attr)
                              (match-string 1 attr))
-                  floatp (or caption label))
+                  floatp (or caption label)
+                 placement     (if (and attr 
+                                        (stringp attr)
+                                        (string-match "[ \t]*\\<placement=\\(\\S-+\\)" attr))
+                                   (match-string 1 attr)
+                                 "[htb]"))
            (setq caption (and caption (org-export-latex-fontify-headline caption)))
             (setq lines (org-split-string raw-table "\n"))
             (apply 'delete-region (list beg end))
@@ -1664,12 +1820,13 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
                        (concat
                         (if longtblp
                             (concat "\\begin{longtable}{" align "}\n")
-                          (if floatp "\\begin{table}[htb]\n"))
+                          (if floatp (format "\\begin{table}%s\n" placement)))
                         (if floatp
                             (format
-                             "\\caption%s{%s}"
+                             "\\caption%s{%s} %s"
                              (if shortn (concat "[" shortn "]") "")
-                             (or caption "")))
+                             (or caption "")
+                            (if label (format "\\label{%s}" label) "")))
                         (if (and longtblp caption) "\\\\\n" "\n")
                         (if (and org-export-latex-tables-centered (not longtblp))
                             "\\begin{center}\n")
@@ -1741,7 +1898,7 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
       (setq tbl (concat "\\begin{center}\n" tbl "\\end{center}")))
     (when floatp
       (setq tbl (concat "\\begin{table}\n"
-                       (format "\\caption%s{%s%s}\n"
+                       (format "\\caption%s{%s}%s\n"
                                (if shortn (format "[%s]" shortn) "")
                                (if label (format "\\label{%s}" label) "")
                                (or caption ""))
@@ -1886,10 +2043,10 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
              (insert (format
                       (org-export-get-coderef-format path desc)
                       (cdr (assoc path org-export-code-refs)))))
-            (radiop (insert (format "\\hyperref[%s]{%s}"
+            (radiop (insert (format org-export-latex-hyperref-format
                                     (org-solidify-link-text raw-path) desc)))
             ((not type)
-             (insert (format "\\hyperref[%s]{%s}"
+             (insert (format org-export-latex-hyperref-format
                              (org-remove-initial-hash
                               (org-solidify-link-text raw-path))
                              desc)))
@@ -1900,7 +2057,7 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
                ;; a LaTeX issue, but we here implement a work-around anyway.
                (setq path (org-export-latex-protect-amp path)
                      desc (org-export-latex-protect-amp desc)))
-             (insert (format org-export-latex-hyperref-format path desc)))
+             (insert (format org-export-latex-href-format path desc)))
 
             ((functionp (setq fnc (nth 2 (assoc type org-link-protocols))))
              ;; The link protocol has a function for formatting the link
@@ -2213,11 +2370,11 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
   "Convert plain text lists in current buffer into LaTeX lists."
   (let (res)
     (goto-char (point-min))
-    (while (org-re-search-forward-unprotected org-list-beginning-re nil t)
+    (while (org-search-forward-unenclosed org-item-beginning-re nil t)
       (beginning-of-line)
       (setq res (org-list-to-latex (org-list-parse-list t)
                                   org-export-latex-list-parameters))
-      (while (string-match "^\\(\\\\item[ \t]+\\)\\[@start:\\([0-9]+\\)\\]"
+      (while (string-match "^\\(\\\\item[ \t]+\\)\\[@\\(?:start:\\)?\\([0-9]+\\)\\]"
                           res)
        (setq res (replace-match
                   (concat (format "\\setcounter{enumi}{%d}"
@@ -2226,7 +2383,7 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
                           "\n"
                           (match-string 1 res))
                   t t res)))
-      (insert res "\n"))))
+      (insert res))))
 
 (defconst org-latex-entities
  '("\\!"