From: Matt Huszagh <huszaghmatt@gmail.com> To: Bastien <bzg@gnu.org> Cc: emacs-orgmode@gnu.org Subject: Re: babel latex headers and image generation commands Date: Sat, 29 Aug 2020 00:02:51 -0700 [thread overview] Message-ID: <CA+X8ke6eM+7REUUXiBAxZ-dV_hr9DdABv2ZTZoOjNXf_vHJeQg@mail.gmail.com> (raw) In-Reply-To: <87y2lynft3.fsf@gmail.com> [-- Attachment #1.1: Type: text/plain, Size: 9587 bytes --] Bastien <bzg@gnu.org> writes: > If you find the time to share your change as a _patch_ (not the whole > updated Elisp function), that will allow more readers on this list to > quickly understand what is at stake. Ok, I've finally gotten around to taking a crack at this. The patch is attached. Basically, it allows a lot more control when converting a latex source block into an svg image file. Specifically, this new method does not place any restrictions on the latex contents (the old svg generation required the use of \documentclass[preview]{standalone}), or on the specific generation commands (it does require first compiling to pdf then to svg, though I guess this could be generalized if necessary). Additionally, it allows you to use a setup independent of the setup used for inline latex snippets. I think this is important because snippets and latex source blocks have different use cases. For instance, I use snippets for simple inline math (e.g. \(x=6\)) and source blocks for complicated full-blown latex pictures and sets of equations, etc. that are not supported by latex fragments. I'll present my use case as an example (see the patch to understand the customizations). ;; this is particular to my use case, see `latex-preamble-by-backend' (defun by-backend (blist) (let ((ret nil)) (if org-export-current-backend (let* ((backend-name org-export-current-backend) (elem (assoc backend-name blist))) (if elem (setq ret (cdr elem)))) (let ((elem (assoc t blist))) (setq ret (cdr elem)))) (eval ret))) ;; custom function for preamble generation (defun latex-preamble-by-backend (params) (concat "\\documentclass{" (cdr (assoc :class params)) "}" "\\definecolor{fg}{rgb}{" (by-backend '((html . "0,0,0") (t . (org-latex-color :foreground)))) "}\n" "\\definecolor{bg}{rgb}{" (by-backend '((html . "1,1,1") (t . (org-latex-color :background)))) "}\n" "\\def\\pc{" (by-backend '((html . "100") (t . "20"))) "}\n")) ;; actual set customization (setq org-babel-latex-preamble (lambda (params) (latex-preamble-by-backend params))) Now if I define a source block: #+header: :class math :results file link replace :file tmp/some-file.svg #+begin_src latex :hidden {\color{fg} \begin{equation*} |z| = \sqrt{x^2 + y^2} \end{equation*} } #+end_src Using my customization above, this will turn into the following latex \documentclass{math}\definecolor{fg}{rgb}{0.819608,0.721569,0.592157} \definecolor{bg}{rgb}{0.0235294,0.137255,0.160784} \def\pc{20} \begin{document}{\color{fg} \begin{equation*} |z| = \sqrt{x^2 + y^2} \end{equation*} }\end{document} which is then turned into an svg with inkscape, though this could be dvisvgm, or whatever you want. Math is a custom document class I've defined. But my function also allows the setting of other classes (which is useful because some classes work better for tikz-like images and others work better for math). In fact, since the preamble generation function can use any of the source block parameters, I could make it do a bunch of other conditional stuff. I've also configured it to set my color scheme in a backend-dependent way. This allows me to get color schemes that match my emacs theme when generating images for viewing within emacs and another color scheme (in my case black foreground, white background) when exporting to html. Note that none of this is enforced on other people. My patch simply allows you to achieve this sort of flexibility. I think this patch needs some discussing. I had some trouble deciding on the best way to implement this functionality because its hard to get anything to be thematically consistent with the current latex execute command, which feels like a collection of loosely-related functionality (for instance, the htlatex backend generates a completely different latex source than the imagemagick backend, even though the outputs could be quite similar -- svg and png). I think there's a lot of room for improvement in the latex execute function that could make it more general and flexible, but it's hard to do this in a way that doesn't break existing workflows. My patch tries to be minimally invasive to these workflows, though it will break workflows in an easily recoverable way for anyone using htlatex for svg output. Anyway, I'd be curious to hear thoughts and I'd be interested to discuss options for further refactoring the latex execute function. Matt On Fri, Aug 28, 2020 at 11:10 PM Matt Huszagh <huszaghmatt@gmail.com> wrote: > Bastien <bzg@gnu.org> writes: > > > If you find the time to share your change as a _patch_ (not the whole > > updated Elisp function), that will allow more readers on this list to > > quickly understand what is at stake. > > Ok, I've finally gotten around to taking a crack at this. The patch is > attached. Basically, it allows a lot more control when converting a > latex source block into an svg image file. > > Specifically, this new method does not place any restrictions on the > latex contents (the old svg generation required the use of > \documentclass[preview]{standalone}), or on the specific generation > commands (it does require first compiling to pdf then to svg, though I > guess this could be generalized if necessary). Additionally, it allows > you to use a setup independent of the setup used for inline latex > snippets. I think this is important because snippets and latex source > blocks have different use cases. For instance, I use snippets for simple > inline math (e.g. \(x=6\)) and source blocks for complicated full-blown > latex pictures and sets of equations, etc. that are not supported by > latex fragments. > > I'll present my use case as an example (see the patch to understand the > customizations). > > ;; this is particular to my use case, see `latex-preamble-by-backend' > (defun by-backend (blist) > (let ((ret nil)) > (if org-export-current-backend > (let* ((backend-name org-export-current-backend) > (elem (assoc backend-name blist))) > (if elem > (setq ret (cdr elem)))) > (let ((elem (assoc t blist))) > (setq ret (cdr elem)))) > (eval ret))) > > ;; custom function for preamble generation > (defun latex-preamble-by-backend (params) > (concat "\\documentclass{" > (cdr (assoc :class params)) > "}" > "\\definecolor{fg}{rgb}{" > (by-backend '((html . "0,0,0") > (t . (org-latex-color :foreground)))) > "}\n" > "\\definecolor{bg}{rgb}{" > (by-backend '((html . "1,1,1") > (t . (org-latex-color :background)))) > "}\n" > "\\def\\pc{" > (by-backend '((html . "100") > (t . "20"))) > "}\n")) > > ;; actual set customization > (setq org-babel-latex-preamble > (lambda (params) > (latex-preamble-by-backend params))) > > Now if I define a source block: > > #+header: :class math :results file link replace :file tmp/some-file.svg > #+begin_src latex :hidden > {\color{fg} > \begin{equation*} > |z| = \sqrt{x^2 + y^2} > \end{equation*} > } > #+end_src > > Using my customization above, this will turn into the following latex > > \documentclass{math}\definecolor{fg}{rgb}{0.819608,0.721569,0.592157} > \definecolor{bg}{rgb}{0.0235294,0.137255,0.160784} > \def\pc{20} > \begin{document}{\color{fg} > \begin{equation*} > |z| = \sqrt{x^2 + y^2} > \end{equation*} > }\end{document} > > which is then turned into an svg with inkscape, though this could be > dvisvgm, or whatever you want. > > Math is a custom document class I've defined. But my function also > allows the setting of other classes (which is useful because some > classes work better for tikz-like images and others work better for > math). In fact, since the preamble generation function can use any of > the source block parameters, I could make it do a bunch of other > conditional stuff. I've also configured it to set my color scheme in a > backend-dependent way. This allows me to get color schemes that match my > emacs theme when generating images for viewing within emacs and another > color scheme (in my case black foreground, white background) when > exporting to html. Note that none of this is enforced on other > people. My patch simply allows you to achieve this sort of flexibility. > > I think this patch needs some discussing. I had some trouble deciding on > the best way to implement this functionality because its hard to get > anything to be thematically consistent with the current latex execute > command, which feels like a collection of loosely-related functionality > (for instance, the htlatex backend generates a completely different > latex source than the imagemagick backend, even though the outputs could > be quite similar -- svg and png). I think there's a lot of room for > improvement in the latex execute function that could make it more > general and flexible, but it's hard to do this in a way that doesn't > break existing workflows. My patch tries to be minimally invasive to > these workflows, though it will break workflows in an easily recoverable > way for anyone using htlatex for svg output. > > Anyway, I'd be curious to hear thoughts and I'd be interested to discuss > options for further refactoring the latex execute function. > > Matt > > [-- Attachment #1.2: Type: text/html, Size: 11594 bytes --] [-- Attachment #2: 0001-ob-latex.el-Make-latex-to-svg-compilation-very-custo.patch --] [-- Type: application/octet-stream, Size: 2876 bytes --] From 0834f59ac9485158c26c4b25ec40df56be2c15ca Mon Sep 17 00:00:00 2001 From: Matt Huszagh <huszaghmatt@gmail.com> Date: Fri, 28 Aug 2020 22:26:05 -0700 Subject: [PATCH] ob-latex.el: Make latex to svg compilation very customizable * lisp/ob-latex.el (org-babel-latex-preamble): Add latex preamble customization. (org-babel-latex-pdf-svg-process): Add customization for converting a pdf to svg. (org-babel-execute:latex): Add specific case for svg generation from latex block. --- lisp/ob-latex.el | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el index 4b343dd14..ba7bb8277 100644 --- a/lisp/ob-latex.el +++ b/lisp/ob-latex.el @@ -70,6 +70,23 @@ :group 'org-babel :type 'string) +(defcustom org-babel-latex-preamble + (lambda (_) + "\\documentclass[preview]{standalone} +\\def\\pgfsysdriver{pgfsys-tex4ht.def} +") + "Closure which evaluates at runtime to the latex preamble. It +takes 1 argument which is the parameters of the source block." + :group 'org-babel + :type 'function) + +(defcustom org-babel-latex-pdf-svg-process + "inkscape --pdf-poppler %f -T -l -o %O" + "Command used to convert a PDF file to an SVG file when +executing a latex source block." + :group 'org-babel + :type 'string) + (defcustom org-babel-latex-htlatex-packages '("[usenames]{color}" "{tikz}" "{color}" "{listings}" "{amsmath}") "Packages to use for htlatex export." @@ -114,12 +131,26 @@ This function is called by `org-babel-execute-src-block'." (mapconcat #'identity headers "\n")))) (org-create-formula-image body out-file org-format-latex-options in-buffer))) + ((string= "svg" extension) + (with-temp-file tex-file + (insert (concat (funcall org-babel-latex-preamble params) + (mapconcat #'identity headers "\n") + "\\begin{document}" + body + "\\end{document}"))) + (let ((tmp-pdf (org-babel-latex-tex-to-pdf tex-file))) + (let* ((log-buf (get-buffer-create "*Org Babel LaTeX Output*")) + (err-msg "org babel latex failed") + (img-out (org-compile-file + tmp-pdf + (list org-babel-latex-pdf-svg-process) + extension err-msg log-buf))) + (shell-command (format "mv %s %s" img-out out-file))))) ((string-suffix-p ".tikz" out-file) (when (file-exists-p out-file) (delete-file out-file)) (with-temp-file out-file (insert body))) - ((and (or (string= "svg" extension) - (string= "html" extension)) + ((and (string= "html" extension) (executable-find org-babel-latex-htlatex)) ;; TODO: this is a very different way of generating the ;; frame latex document than in the pdf case. Ideally, both -- 2.28.0
next prev parent reply other threads:[~2020-08-29 7:03 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-02-04 7:39 Matt Huszagh 2020-02-04 21:19 ` Matt Huszagh 2020-02-04 23:38 ` Matt Huszagh 2020-02-10 7:21 ` Bastien [not found] ` <87y2lynft3.fsf@gmail.com> 2020-08-29 7:02 ` Matt Huszagh [this message] 2020-09-02 17:32 ` [PATCH] " Matt Huszagh 2020-09-02 18:53 ` Matt Huszagh 2020-09-06 6:18 ` Bastien 2020-09-09 19:43 ` Matt Huszagh 2020-10-24 12:30 ` Bastien 2020-10-24 16:39 ` Matt Huszagh 2020-12-14 8:19 ` Bastien 2020-09-06 5:59 ` Bastien
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style List information: https://www.orgmode.org/ * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=CA+X8ke6eM+7REUUXiBAxZ-dV_hr9DdABv2ZTZoOjNXf_vHJeQg@mail.gmail.com \ --to=huszaghmatt@gmail.com \ --cc=bzg@gnu.org \ --cc=emacs-orgmode@gnu.org \ --subject='Re: babel latex headers and image generation commands' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Code repositories for project(s) associated with this 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).