From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thibault Marin Subject: [PATCH] EPS generation from latex source block Date: Sun, 14 Feb 2016 03:14:52 -0600 Message-ID: <877fi7fyb7.fsf@dell-desktop.WORKGROUP> Reply-To: thibaultmarin Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54450) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aUslg-0003Oi-Qz for emacs-orgmode@gnu.org; Sun, 14 Feb 2016 04:15:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aUsld-0003aU-Ii for emacs-orgmode@gnu.org; Sun, 14 Feb 2016 04:15:00 -0500 Received: from mail-yk0-x22c.google.com ([2607:f8b0:4002:c07::22c]:35178) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aUslc-0003aB-VO for emacs-orgmode@gnu.org; Sun, 14 Feb 2016 04:14:57 -0500 Received: by mail-yk0-x22c.google.com with SMTP id r207so50312265ykd.2 for ; Sun, 14 Feb 2016 01:14:55 -0800 (PST) Received: from dell-desktop.WORKGROUP (99-47-196-62.lightspeed.dctril.sbcglobal.net. [99.47.196.62]) by smtp.gmail.com with ESMTPSA id c84sm16587957ywb.41.2016.02.14.01.14.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 14 Feb 2016 01:14:54 -0800 (PST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org Here is a small patch I use to produce TikZ EPS files from LaTeX source blocks. >From d750c26cabc87e4917974df8080714d5d7e2c9a8 Mon Sep 17 00:00:00 2001 From: thibault Date: Sun, 14 Feb 2016 03:07:20 -0600 Subject: [PATCH] Add eps output to ob-latex (without imagemagick) To: emacs-orgmode@gnu.org * ob-latex: Accept output file with EPS extension without requiring the imagemagick option. This can be used to generate EPS files from TikZ in LaTeX source blocks. * ox-latex: Add `org-latex-eps-process' based on `org-latex-pdf-process'. Default build uses dvips and ghostscript to produce an EPS file with correct bounding box. Add an extra optional argument to `org-latex-compile' to pass the output file type (pdf or eps) --- lisp/ob-latex.el | 18 +++++++++++---- lisp/ox-latex.el | 67 +++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el index a8fbe29..416e5be 100644 --- a/lisp/ob-latex.el +++ b/lisp/ob-latex.el @@ -158,7 +158,7 @@ This function is called by `org-babel-execute-src-block'." ".html") out-file) (error "HTML file produced but SVG file requested"))))) - ((or (string-match "\\.pdf$" out-file) imagemagick) + ((or (string-match "\\.pdf$" out-file) (string-match "\\.eps$" out-file) imagemagick) (with-temp-file tex-file (require 'ox-latex) (insert @@ -189,9 +189,14 @@ This function is called by `org-babel-execute-src-block'." "\n\\end{preview}\n\\end{document}\n") (concat "\n\\begin{document}\n" body "\n\\end{document}\n")))) (when (file-exists-p out-file) (delete-file out-file)) - (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file))) + (let ((transient-pdf-file + (cond ((string-match "\\.pdf$" out-file) + (org-babel-latex-tex-to-pdf tex-file)) + ((and (not imagemagick) (string-match "\\.eps$" out-file)) + (org-babel-latex-tex-to-eps tex-file))))) (cond - ((string-match "\\.pdf$" out-file) + ((or (string-match "\\.pdf$" out-file) + (and (not imagemagick) (string-match "\\.eps$" out-file))) (rename-file transient-pdf-file out-file)) (imagemagick (org-babel-latex-convert-pdf @@ -199,7 +204,7 @@ This function is called by `org-babel-execute-src-block'." (when (file-exists-p transient-pdf-file) (delete-file transient-pdf-file)))))) ((string-match "\\.\\([^\\.]+\\)$" out-file) - (error "Can not create %s files, please specify a .png or .pdf file or try the :imagemagick header argument" + (error "Can not create %s files, please specify a .png, .pdf or .eps file or try the :imagemagick header argument" (match-string 1 out-file)))) nil) ;; signal that output has already been written to file body)) @@ -216,6 +221,11 @@ This function is called by `org-babel-execute-src-block'." (require 'ox-latex) (org-latex-compile file)) +(defun org-babel-latex-tex-to-eps (file) + "Generate a pdf file according to the contents FILE." + (require 'ox-latex) + (org-latex-compile file nil "eps")) + (defun org-babel-prep-session:latex (_session _params) "Return an error because LaTeX doesn't support sessions." (error "LaTeX does not support sessions")) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 9285aac..eb0c883 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1166,6 +1166,36 @@ file name as its single argument." ("latexmk -g -pdflatex=\"%latex\" %f")) (function))) +(defcustom org-latex-eps-dpi 300 + "Resolution for EPS image generation. +This is passed to the ghostscript command when adjusting the bounding +box." + :group 'org-export-latex + :type 'integer + :version "25.1" + :package-version '(Org . "9.0")) + +(defcustom org-latex-eps-process + '("latex -interaction nonstopmode %f" + "dvips -R -K0 -E %b.dvi -o %b_t.eps" + "gs -dNOPAUSE -dBATCH -sDEVICE=eps2write -r600 -sOutputFile=%b.eps %b_t.eps") + "Commands to process a LaTeX file to an EPS file. +This is a list of commands built similarly to +`org-latex-pdf-process'. %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), %o by the base directory of the +file. + +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 '((string) + (function)) + :version "25.1" + :package-version '(Org . "9.0")) + (defcustom org-latex-logfiles-extensions '("aux" "bcf" "blg" "fdb_latexmk" "fls" "figlist" "idx" "log" "nav" "out" "ptc" "run.xml" "snm" "toc" "vrb" "xdv") @@ -3515,18 +3545,27 @@ 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 output-type) "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-PROCESS. +ORG-LATEX-PROCESS defaults to `org-latex-pdf-process'. An alternative +to produce EPS output instead of PDF is to use +`org-latex-eps-process'. 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))) + (unless output-type (setq output-type "pdf")) + (let* ((org-latex-process + (cond ((string= output-type "pdf") org-latex-pdf-process) + ((string= output-type "eps") org-latex-eps-process) + (t nil))) + (output-type-str (upcase output-type)) + (base-name (file-name-sans-extension (file-name-nondirectory texfile))) (full-name (file-truename texfile)) (compiler (or (with-temp-buffer (save-excursion (insert-file-contents full-name)) @@ -3547,23 +3586,24 @@ Return PDF file name or an error if it couldn't be produced." (save-window-excursion (cond ;; A function is provided: Apply it. - ((functionp org-latex-pdf-process) - (funcall org-latex-pdf-process (shell-quote-argument texfile))) + ((functionp org-latex-process) + (funcall org-latex-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', + ;; "%latex" and "%bibtex" is used in `org-latex-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) + ((consp org-latex-process) (let ((outbuf (and (not snippet) - (get-buffer-create "*Org PDF LaTeX Output*"))) + (get-buffer-create + (format "*Org %s LaTeX Output*" output-type-str)))) (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) + (dolist (command org-latex-process) (let ((c (replace-regexp-in-string "%\\(latex\\|bibtex\\)\\>" (lambda (str) (upcase (substring str 0 2))) @@ -3572,8 +3612,8 @@ Return PDF file name or an error if it couldn't be produced." ;; 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"))) + (t (error (format "No valid command to process to %s" output-type-str)))) + (let ((pdffile (concat out-dir base-name "." output-type))) ;; Check for process failure. Provide collected errors if ;; possible. (if (or (not (file-exists-p pdffile)) @@ -3581,7 +3621,8 @@ Return PDF file name or an error if it couldn't be produced." ;; (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)) + (error (format "%s file %s wasn't produced" + output-type-str pdffile)) ;; Else remove log files, when specified, and signal end of ;; process to user, along with any error encountered. (unless snippet @@ -3593,7 +3634,7 @@ Return PDF file name or an error if it couldn't be produced." "\\." (regexp-opt org-latex-logfiles-extensions)))) (delete-file file))) - (message (concat "PDF file produced" + (message (concat output-type-str "file produced" (cond ((eq warnings 'error) " with errors.") (warnings (concat " with warnings: " warnings)) -- 2.7.0.rc3