emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [PATCH] EPS generation from latex source block
@ 2016-02-14  9:14 Thibault Marin
  0 siblings, 0 replies; only message in thread
From: Thibault Marin @ 2016-02-14  9:14 UTC (permalink / raw)
  To: emacs-orgmode


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

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2016-02-14  9:15 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-14  9:14 [PATCH] EPS generation from latex source block Thibault Marin

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).