From dc4989ccf41f09e7fce08036f89e9274ead4e257 Mon Sep 17 00:00:00 2001 From: TEC Date: Sun, 8 May 2022 15:28:29 +0800 Subject: [PATCH 09/10] ox-latex: Support setting engraved theme per-block * lisp/ox-latex.el (org-latex-src-block--engraved, org-latex-src--engrave-code, org-latex-inline-src-block--engraved, org-latex-generate-engraved-preamble): Allow for the engraved theme used to be set on a per-src-block basis with #+attr_latex: :engraved-theme THEME. Extra setup code is now generated in `org-latex-generate-engraved-preamble'. To facilitate the application of themes to src blocks, `org-latex-src--engrave-code' now takes on a larger portion of the transcoding work. --- lisp/ox-latex.el | 113 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 24 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 21541e9aa..528243a59 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1285,7 +1285,27 @@ (defun org-latex-generate-engraved-preamble (info syntax-colours-p) (let* ((engraved-options (plist-get info :latex-engraved-options)) (engraved-preamble (plist-get info :latex-engraved-preamble)) - (engraved-theme (plist-get info :latex-engraved-theme))) + (engraved-theme (plist-get info :latex-engraved-theme)) + (engraved-themes + (cl-delete-duplicates + (org-element-map + (plist-get info :parse-tree) + '(src-block inline-src-block) + (lambda (src) + (plist-get + (org-export-read-attribute :attr_latex src) + :engraved-theme)) + info))) + (gen-theme-spec + (lambda (theme) + (if (eq engrave-faces-latex-output-style 'preset) + (engrave-faces-latex-gen-preamble (when theme (intern theme))) + (engrave-faces-latex-gen-preamble-line + 'default + (alist-get 'default + (if theme + (engrave-faces-get-theme (intern theme)) + engrave-faces-current-preset-style))))))) (when (string-match "^[ \t]*\\[FVEXTRA-SETUP\\][ \t]*\n?" engraved-preamble) (setq engraved-preamble (replace-match @@ -1315,10 +1335,31 @@ (defun org-latex-generate-engraved-preamble (info syntax-colours-p) (concat "\n% Setup for code blocks [1/2]\n\n" engraved-preamble - "\n\n% Setup for code blocks [2/2]: syntax highlighting colors\n" + "\n\n% Setup for code blocks [2/2]: syntax highlighting colors\n\n" (if (require 'engrave-faces-latex nil t) - (engrave-faces-latex-gen-preamble - (when engraved-theme (intern engraved-theme))) + (if engraved-themes + (concat + (mapconcat + (lambda (theme) + (format + "\n\\newcommand{\\engravedtheme%s}{%%\n%s\n}" + (replace-regexp-in-string "[^A-Za-z]" "" theme) + (replace-regexp-in-string + "newcommand" "renewcommand" + (replace-regexp-in-string + "#" "##" + (funcall gen-theme-spec theme))))) + engraved-themes + "\n") + "\n\n" + (cond + ((memq engraved-theme engraved-themes) + (concat "\\engravedtheme" + (replace-regexp-in-string + "[^A-Za-z]" "" engraved-theme) + "\n")) + (t (funcall gen-theme-spec engraved-theme)))) + (funcall gen-theme-spec engraved-theme)) (message "Cannot engrave source blocks. Consider installing `engrave-faces'.") "% WARNING syntax highlighting unavailible as engrave-faces-latex was missing.\n") "\n") @@ -2361,10 +2402,11 @@ (defun org-latex-inline-src-block--minted (info code lang) mint-lang code))) -(defun org-latex-inline-src-block--engraved (_info code lang) +(defun org-latex-inline-src-block--engraved (info code lang) "Transcode an inline src block's content from Org to LaTeX, using engrave-faces. INFO, CODE, and LANG are provided by `org-latex-inline-src-block'." - (format "\\Verb{%s}" (org-latex-src--engrave-code code lang))) + (org-latex-src--engrave-code + code lang nil (plist-get info :latex-engraved-options) t)) (defun org-latex-inline-src-block--listings (info code lang) "Transcode an inline src block's content from Org to LaTeX, using lstlistings. @@ -3349,13 +3391,18 @@ (cl-defun org-latex-src-block--minted ;; Return value. (format float-env body))) -(defun org-latex-src--engrave-code (content lang) - "Engrave CONTENT to LaTeX in a LANG-mode buffer, and give the result." +(defun org-latex-src--engrave-code (content lang &optional theme options inline) + "Engrave CONTENT to LaTeX in a LANG-mode buffer, and give the result. +When THEME is non-nil, it will be used." (if (require 'engrave-faces-latex nil t) (let* ((lang-mode (and lang (org-src-get-lang-mode lang))) + (engrave-faces-current-preset-style + (if theme + (engrave-faces-get-theme theme) + engrave-faces-current-preset-style)) (engraved-buffer (with-temp-buffer - (insert content) + (insert (string-trim-right content "\n")) (when lang-mode (if (functionp lang-mode) (funcall lang-mode) @@ -3364,9 +3411,27 @@ (defun org-latex-src--engrave-code (content lang) (engrave-faces-latex-buffer))) (engraved-code (with-current-buffer engraved-buffer - (buffer-string)))) + (buffer-string))) + (engraved-options + (when options + (concat "[" + (if (listp options) + (org-latex--make-option-string options) + options) + "]"))) + (engraved-wrapped + (if inline + (concat "\\Verb" engraved-options "{" engraved-code "}") + (concat "\\begin{Code}\\begin{Verbatim}" engraved-options "\n" + engraved-code "\n\\end{Verbatim}\n\\end{Code}")))) (kill-buffer engraved-buffer) - engraved-code) + (if theme + (concat "{\\engravedtheme" + (replace-regexp-in-string "[^A-Za-z]" "" + (symbol-name theme)) + engraved-wrapped + "}") + engraved-wrapped)) (user-error "Cannot engrave code as `engrave-faces-latex' is unavailible."))) (cl-defun org-latex-src-block--engraved @@ -3394,7 +3459,15 @@ (cl-defun org-latex-src-block--engraved placement) "%s\n\\end{listing}")) (t "%s"))) - (options (plist-get info :latex-engraved-options)) + (options + (let ((engraved-options (plist-get info :latex-engraved-options)) + (local-options (plist-get attributes :options))) + (append + (when (and num-start (not (assoc "linenos" engraved-options))) + `(("linenos") + ("firstnumber" ,(number-to-string (1+ num-start))))) + (and local-options (list local-options))))) + (engraved-theme (plist-get attributes :engraved-theme)) (content (let* ((code-info (org-export-unravel-code src-block)) (max-width @@ -3416,18 +3489,10 @@ (cl-defun org-latex-src-block--engraved (format "(%s)" ref))))) nil (and retain-labels (cdr code-info))))) (body - (format - "\\begin{Code}\n\\begin{Verbatim}[%s]\n%s\\end{Verbatim}\n\\end{Code}" - ;; Options. - (concat - (org-latex--make-option-string - (append - (when (and num-start (not (assoc "linenos" options))) - `(("linenos") - ("firstnumber" ,(number-to-string (1+ num-start))))) - (let ((local-options (plist-get attributes :options))) - (and local-options (list local-options)))))) - (org-latex-src--engrave-code content lang)))) + (org-latex-src--engrave-code + content lang + (when engraved-theme (intern engraved-theme)) + options))) (format float-env body))) (cl-defun org-latex-src-block--listings -- 2.35.3