>From 4e40deddfb342135b78df83fc5a05ddbce965300 Mon Sep 17 00:00:00 2001 From: Feng Shu Date: Fri, 13 May 2016 20:12:22 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's info * ox-html.el (org-html-with-latex): Add dvisvgm support. (org-html-with-latex): Add dvisvgm support. (org-html-format-latex): "ltxpng" -> "ltximg". (org-html-latex-environment): Add dvisvgm support. (org-html-latex-fragment): Add dvisvgm support. * org.el (org-latex-create-formula-image-program): Add dvisvgm. (org-latex-preview-ltximg-directory): Rename from `org-latex-preview-ltximg-directory'. (org--format-latex-make-overlay): Add optional image-type, which used to deal with svg. (org-toggle-latex-fragment): "org-ltxpng" -> "org-ltximg". (org-format-latex): Add dvisvgm support. (org-create-formula-image): Add dvisvgm case. (org-create-formula-image-with-dvisvgm): New function, deal with latex formula with dvisvgm command. * org.texi (@LaTeX{} fragments): Add dvisvgm information. (Previewing @LaTeX{} fragments): Add dvisvgm information. (Math formatting in HTML export): Add dvisvgm information. (Working with @LaTeX{} math snippets): Add dvisvgm information. --- doc/org.texi | 39 ++++++++----- lisp/org.el | 110 ++++++++++++++++++++++++++++------- lisp/ox-html.el | 23 ++++---- lisp/ox-latex.el | 171 +++++++++++++++++++++++++++++++++++-------------------- 4 files changed, 237 insertions(+), 106 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 17b01c2..286fabb 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -10393,10 +10393,10 @@ snippets will be identified as @LaTeX{} source code: @item Environments of any address@hidden MathJax is used, only the environments recognized by MathJax will be processed. When address@hidden program or @file{imagemagick} suite is used to create images, -any @LaTeX{} environment will be handled.}. The only requirement is that the address@hidden statement appears on a new line, at the beginning of the line -or after whitespaces only. address@hidden program, @file{dvisvgm} program or @file{imagemagick} suite is +used to create images, any @LaTeX{} environment will be handled.}. The only +requirement is that the @code{\begin} statement appears on a new line, at the +beginning of the line or after whitespaces only. @item Text within the usual @LaTeX{} math delimiters. To avoid conflicts with currency specifications, single @samp{$} characters are only recognized as @@ -10444,10 +10444,10 @@ lines: @cindex @LaTeX{} fragments, preview @vindex org-latex-create-formula-image-program -If you have a working @LaTeX{} installation and either @file{dvipng} or address@hidden address@hidden are respectively available at address@hidden://sourceforge.net/projects/dvipng/} and from the @file{imagemagick} -suite. Choose the converter by setting the variable +If you have a working @LaTeX{} installation and @file{dvipng}, @file{dvisvgm} +or @file{convert} address@hidden are respectively available at address@hidden://sourceforge.net/projects/dvipng/}, @url{http://dvisvgm.bplaced.net/} +and from the @file{imagemagick} suite. Choose the converter by setting the variable @code{org-latex-create-formula-image-program} accordingly.}, @LaTeX{} fragments can be processed to produce images of the typeset expressions to be used for inclusion while exporting to HTML (see @address@hidden fragments}), @@ -11713,6 +11713,7 @@ You could use @code{http} addresses just as well. @subsection Math formatting in HTML export @cindex MathJax @cindex dvipng address@hidden dvisvgm @cindex imagemagick @LaTeX{} math snippets (@address@hidden fragments}) can be displayed in two @@ -11737,13 +11738,18 @@ template can be configure via @code{org-html-mathjax-template}. If you prefer, you can also request that @LaTeX{} fragments are processed into small images that will be inserted into the browser page. Before the availability of MathJax, this was the default method for Org files. This -method requires that the @file{dvipng} program or @file{imagemagick} suite is -available on your system. You can still get this processing with +method requires that the @file{dvipng} program, @file{dvisvgm} or address@hidden suite is available on your system. You can still get +this processing with @example #+OPTIONS: tex:dvipng @end example address@hidden +#+OPTIONS: tex:dvisvgm address@hidden example + or: @example @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng address@hidden dvisvgm @cindex imagemagick @item PNG images @@ -12917,16 +12924,20 @@ This option is activated on a per-file basis with #+OPTIONS: tex:dvipng @end example address@hidden +#+OPTIONS: tex:dvisvgm address@hidden example + or: @example #+OPTIONS: tex:imagemagick @end example -With this option, @LaTeX{} fragments are processed into PNG images and the -resulting images are embedded in the exported document. This method requires -that the @file{dvipng} program or @file{imagemagick} suite be available on -your system. +With this option, @LaTeX{} fragments are processed into PNG or SVG images and +the resulting images are embedded in the exported document. This method requires +that the @file{dvipng} program, @file{dvisvgm} or @file{imagemagick} suite be +available on your system. @end enumerate @node Working with MathML or OpenDocument formula files diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..87f8d3a 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3983,17 +3983,24 @@ When using LaTeXML set this option to "Program to convert LaTeX fragments with. dvipng Process the LaTeX fragments to dvi file, then convert - dvi files to png files using dvipng. - This will also include processing of non-math environments. + dvi files to png files using dvipng. + This will also include processing of non-math environments. +dvisvgm Process the LaTeX fragments to dvi/xdv file, then convert + dvi/xdv files to svg files using dvipng. + This will also include processing of non-math environments. imagemagick Convert the LaTeX fragments to pdf files and use imagemagick - to convert pdf files to png files" + to convert pdf files to png files." :group 'org-latex :version "24.1" :type '(choice (const :tag "dvipng" dvipng) + (const :tag "dvisvgm" dvisvgm) (const :tag "imagemagick" imagemagick))) -(defcustom org-latex-preview-ltxpng-directory "ltxpng/" +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(defcustom org-latex-preview-ltximg-directory "ltximg/" "Path to store latex preview images. A relative path here creates many directories relative to the processed org files paths. An absolute path puts all preview @@ -18996,9 +19003,10 @@ looks only before point, not after." (org-in-regexp "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*"))) -(defun org--format-latex-make-overlay (beg end image) +(defun org--format-latex-make-overlay (beg end image &optional image-type) "Build an overlay between BEG and END using IMAGE file." - (let ((ov (make-overlay beg end))) + (let ((ov (make-overlay beg end)) + (image-type (or image-type 'png))) (overlay-put ov 'org-overlay-type 'org-latex-overlay) (overlay-put ov 'evaporate t) (overlay-put ov @@ -19008,10 +19016,10 @@ looks only before point, not after." (if (featurep 'xemacs) (progn (overlay-put ov 'invisible t) - (overlay-put ov 'end-glyph (make-glyph (vector 'png :file image)))) + (overlay-put ov 'end-glyph (make-glyph (vector image-type :file image)))) (overlay-put ov 'display - (list 'image :type 'png :file image :ascent 'center))))) + (list 'image :type image-type :file image :ascent 'center))))) (defun org--list-latex-overlays (&optional beg end) "List all Org LaTeX overlays in current buffer. @@ -19092,7 +19100,7 @@ for all fragments in the buffer." (narrow-to-region beg end)))))) (let ((file (buffer-file-name (buffer-base-buffer)))) (org-format-latex - (concat org-latex-preview-ltxpng-directory "org-ltxpng") + (concat org-latex-preview-ltximg-directory "org-ltximg") ;; Emacs cannot overlay images from remote hosts. ;; Create it in `temporary-file-directory' instead. (if (or (not file) (file-remote-p file)) @@ -19123,7 +19131,7 @@ Some of the options can be changed using the variable checkdir-flag) (goto-char (point-min)) ;; Optimize overlay creation: (info "(elisp) Managing Overlays"). - (when (and overlays (memq processing-type '(dvipng imagemagick))) + (when (and overlays (memq processing-type '(dvipng dvisvgm imagemagick))) (overlay-recenter (point-max))) (while (re-search-forward math-regexp nil t) (unless (and overlays @@ -19148,7 +19156,7 @@ Some of the options can be changed using the variable (if (string= (match-string 0 value) "$$") (insert "\\[" (substring value 2 -2) "\\]") (insert "\\(" (substring value 1 -1) "\\)")))) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) ;; Process to an image. (cl-incf cnt) (goto-char beg) @@ -19172,9 +19180,11 @@ Some of the options can be changed using the variable org-latex-packages-alist org-format-latex-options forbuffer value fg bg)))) + (imagetype (if (eq processing-type 'dvisvgm) + 'svg 'png)) (absprefix (expand-file-name prefix dir)) - (linkfile (format "%s_%s.png" prefix hash)) - (movefile (format "%s_%s.png" absprefix hash)) + (linkfile (format "%s_%s.%s" prefix hash imagetype)) + (movefile (format "%s_%s.%s" absprefix hash imagetype)) (sep (and block-type "\n\n")) (link (concat sep "[[file:" linkfile "]]" sep)) (options @@ -19196,7 +19206,7 @@ Some of the options can be changed using the variable (when (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay) (delete-overlay o))) - (org--format-latex-make-overlay beg end movefile) + (org--format-latex-make-overlay beg end movefile imagetype) (goto-char end)) (delete-region beg end) (insert @@ -19315,10 +19325,10 @@ inspection." (defun org-create-formula-image (string tofile options buffer &optional type) "Create an image from LaTeX source using dvipng or convert. -This function calls either `org-create-formula-image-with-dvipng' -or `org-create-formula-image-with-imagemagick' depending on the -value of `org-latex-create-formula-image-program' or on the value -of the optional TYPE variable. +This function calls `org-create-formula-image-with-dvipng' +`org-create-formula-image-with-dvisvgm' or `org-create-formula-image-with-imagemagick' +depending on the value of `org-latex-create-formula-image-program' or +on the value of the optional TYPE variable. Note: ultimately these two function should be combined as they share a good deal of logic." @@ -19330,12 +19340,16 @@ share a good deal of logic." (org-check-external-command "dvipng" "needed to convert LaTeX fragments to images") #'org-create-formula-image-with-dvipng) + (dvisvgm + (org-check-external-command + "dvisvgm" "needed to convert LaTeX fragments to images") + #'org-create-formula-image-with-dvisvgm) (imagemagick (org-check-external-command "convert" "you need to install imagemagick") #'org-create-formula-image-with-imagemagick) (t (error - "Invalid value of `org-latex-create-formula-image-program'"))) + "Invalid value of `org-latex-create-formula-image-program'"))) string tofile options buffer)) (declare-function org-export-get-backend "ox" (name)) @@ -19429,6 +19443,64 @@ horizontal and vertical directions." (delete-file (concat texfilebase e)))) pngfile)))) +(defun org-create-formula-image-with-dvisvgm (string tofile options buffer) + "This calls dvisvgm." + (require 'ox-latex) + (let* ((tmpdir (if (featurep 'xemacs) + (temp-directory) + temporary-file-directory)) + (texfilebase (make-temp-name + (expand-file-name "orgtex" tmpdir))) + (texfile (concat texfilebase ".tex")) + (dvifile (concat texfilebase ".dvi")) + (xdvfile (concat texfilebase ".xdv")) + (svgfile (concat texfilebase ".svg")) + (scale (number-to-string (or (plist-get options (if buffer :scale :html-scale)) 2.0))) + (fg (or (plist-get options (if buffer :foreground :html-foreground)) + "Black")) + (bg (or (plist-get options (if buffer :background :html-background)) + "Transparent"))) + (if (eq fg 'default) (setq fg (org-latex-color :foreground)) + (setq fg (org-latex-color-format fg))) + (if (eq bg 'default) (setq bg (org-latex-color :background)) + (setq bg (org-latex-color-format + (if (string= bg "Transparent") "white" bg)))) + (let ((latex-header (org-create-formula--latex-header))) + (with-temp-file texfile + (insert latex-header) + (insert "\n\\begin{document}\n" + "\\definecolor{fg}{rgb}{" fg "}\n" + "\\definecolor{bg}{rgb}{" bg "}\n" + "\n\\pagecolor{bg}\n" + "\n{\\color{fg}\n" + string + "\n}\n" + "\n\\end{document}\n"))) + (org-latex-compile texfile t '(:name dvisvgm :need dvi)) + (if (not (or (file-exists-p dvifile) + (file-exists-p xdvfile))) + (progn (message "Failed to create dvi or xdv file from %s" texfile) nil) + (ignore-errors + (call-process "dvisvgm" nil nil nil + (if (file-exists-p dvifile) + dvifile + xdvfile) + "-n" + "-b" "min" + "-c" scale + "-o" svgfile)) + (if (not (file-exists-p svgfile)) + (if org-format-latex-signal-error + (error "Failed to create svg file from %s" texfile) + (message "Failed to create svg file from %s" texfile) + nil) + ;; Use the requested file name and clean up + (copy-file svgfile tofile 'replace) + (dolist (e '(".dvi" ".xdv" ".tex" ".aux" ".log" ".svg" ".out")) + (when (file-exists-p (concat texfilebase e)) + (delete-file (concat texfilebase e)))) + svgfile)))) + (declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) (defun org-create-formula-image-with-imagemagick (string tofile options buffer) "This calls convert, which is included into imagemagick." diff --git a/lisp/ox-html.el b/lisp/ox-html.el index b188c38..182b729 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -818,19 +818,22 @@ e.g. \"tex:mathjax\". Allowed values are: nil Ignore math snippets. `verbatim' Keep everything in verbatim -`dvipng' Process the LaTeX fragments to images. This will also - include processing of non-math environments. +`dvipng' Process the LaTeX fragments to png images. This will also + include processing of non-math environments. +`dvisvgm' Process the LaTeX fragments to svg images. This will also + include processing of non-math environments. `imagemagick' Convert the LaTeX fragments to pdf files and use - imagemagick to convert pdf files to png files. + imagemagick to convert pdf files to png files. `mathjax' Do MathJax preprocessing and arrange for MathJax.js to - be loaded. + be loaded. t Synonym for `mathjax'." :group 'org-export-html :version "24.4" :package-version '(Org . "8.0") :type '(choice (const :tag "Do not process math in any way" nil) - (const :tag "Use dvipng to make images" dvipng) + (const :tag "Use dvipng to make png images" dvipng) + (const :tag "Use dvisvgm to make svg images" dvisvgm) (const :tag "Use imagemagick to make images" imagemagick) (const :tag "Use MathJax to display math" mathjax) (const :tag "Leave math verbatim" verbatim))) @@ -2760,8 +2763,8 @@ CONTENTS is nil. INFO is a plist holding contextual information." (defun org-html-format-latex (latex-frag processing-type info) "Format a LaTeX fragment LATEX-FRAG into HTML. PROCESSING-TYPE designates the tool used for conversion. It is -a symbol among `mathjax', `dvipng', `imagemagick', `verbatim' nil -and t. See `org-html-with-latex' for more information. INFO is +a symbol among `mathjax', `dvipng', `dvisvgm', `imagemagick', `verbatim' +nil and t. See `org-html-with-latex' for more information. INFO is a plist containing export properties." (let ((cache-relpath "") (cache-dir "")) (unless (eq processing-type 'mathjax) @@ -2777,7 +2780,7 @@ a plist containing export properties." "\n") "\n"))))) (setq cache-relpath - (concat "ltxpng/" + (concat "ltximg/" (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) @@ -2801,7 +2804,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (let ((formula-link (org-html-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) @@ -2822,7 +2825,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (let ((formula-link (org-html-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 7fa68c5..6599721 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 AUCTeX or the Emacs LaTeX mode. This function should accept the -file name as its single argument." +file name as its single argument. + +User can set this variable to a plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -2300,11 +2325,11 @@ used as a communication channel." (when (org-string-nw-p height) (setq options (concat options ",height=" height))) (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))) - (setq options (concat options ",page=" search-option)))) + (when (and search-option + (equal filetype "pdf") + (org-string-match-p "\\`[0-9]+\\'" search-option) + (not (org-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)) "") @@ -3515,7 +3540,7 @@ Return PDF file's name." async subtreep visible-only body-only ext-plist (lambda (file) (org-latex-compile file))))) -(defun org-latex-compile (texfile &optional snippet) +(defun org-latex-compile (texfile &optional snippet caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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)) @@ -3544,62 +3579,72 @@ Return PDF file name or an error if it couldn't be produced." (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. Note that while - ;; "%latex" and "%bibtex" is used in `org-latex-pdf-process', - ;; they are replaced with "%L" and "%B" to adhere to - ;; format-spec. 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*"))) - (spec (list (cons ?B (shell-quote-argument org-latex-bib-compiler)) - (cons ?L (shell-quote-argument compiler)) - (cons ?b (shell-quote-argument base-name)) - (cons ?f (shell-quote-argument full-name)) - (cons ?o (shell-quote-argument out-dir))))) - (dolist (command org-latex-pdf-process) - (let ((c (replace-regexp-in-string - "%\\(latex\\|bibtex\\)\\>" - (lambda (str) (upcase (substring str 0 2))) - command))) - (shell-command (format-spec c spec) 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 (cl-subseq (nth 5 (file-attributes pdffile)) 0 2) - (cl-subseq time 0 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)))) + (let* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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. Note that while + ;; "%latex" and "%bibtex" is used in `org-latex-pdf-process', + ;; they are replaced with "%L" and "%B" to adhere to + ;; format-spec. Output is redirected to "*Org PDF LaTeX + ;; Output*" buffer. + ((consp latex-pdf-process) + (let ((outbuf (and (not snippet) + (get-buffer-create "*Org PDF LaTeX Output*"))) + (spec (list (cons ?B (shell-quote-argument org-latex-bib-compiler)) + (cons ?L (shell-quote-argument compiler)) + (cons ?b (shell-quote-argument base-name)) + (cons ?f (shell-quote-argument full-name)) + (cons ?o (shell-quote-argument out-dir))))) + (dolist (command latex-pdf-process) + (let ((c (replace-regexp-in-string + "%\\(latex\\|bibtex\\)\\>" + (lambda (str) (upcase (substring str 0 2))) + command))) + (shell-command (format-spec c spec) 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 (cl-subseq (nth 5 (file-attributes pdffile)) 0 2) + (cl-subseq time 0 2))) + ;; When compile a tex snippet, we may only need dvi file + (unless snippet + (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))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4