From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id UGpZBaFNdmK4/gAAbAwnHQ (envelope-from ) for ; Sat, 07 May 2022 12:44:49 +0200 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id IAZxBKFNdmLubQAAG6o9tA (envelope-from ) for ; Sat, 07 May 2022 12:44:49 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id E41A622285 for ; Sat, 7 May 2022 12:44:47 +0200 (CEST) Received: from localhost ([::1]:56514 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nnHva-0002Yz-EU for larch@yhetil.org; Sat, 07 May 2022 06:44:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52480) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nnHsx-000198-4m for emacs-orgmode@gnu.org; Sat, 07 May 2022 06:42:04 -0400 Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]:44677) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nnHsr-0003FQ-Tn for emacs-orgmode@gnu.org; Sat, 07 May 2022 06:42:02 -0400 Received: by mail-pl1-x630.google.com with SMTP id q4so6795470plr.11 for ; Sat, 07 May 2022 03:41:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:references:user-agent:in-reply-to :message-id:mime-version; bh=95xnGODyx2dCgUwt5i40ldhKV4PbSO7xvK3d5rpAhJQ=; b=l2IB/5RGcL4hf9aUEm7TvYun0dOhSkOJXTW2M6U9WlqoMOxKvvULInP3tHZsZMun5p GYHITACV8SFIplL6lAu4QOKU0m+VjBjfH3RZJtrqTDRSPZOVJWYVXKtRxMOFFHD67X6a lqDByZ+vadpNZ4dONjnEgew2S0C9K30CH9EUeZ2P3ZnoAwNw3PxfUgrU2k7UGgg0WezF cUaDbI6STYXFDhncMZKbskJEdTs3CBjYCkfbrJ/EWwq+CYZK7MjzWuPxZk+gqFU2W4T/ JeGFiw35+TYP7+nzeFvjr6D8KU8+q2+xXHoZ7Yvaj5vJoYARAbxdNeduVi+ZqNp+fS6k p+XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:references:user-agent :in-reply-to:message-id:mime-version; bh=95xnGODyx2dCgUwt5i40ldhKV4PbSO7xvK3d5rpAhJQ=; b=pyuJft9cQDYQK//Yqsl+Pxr0l/6nZC9BfChDxcWqCj3DiAaaDxc//UCMz5LTITfMu/ 8IM4WzSwsNhc1eEOzUs72yKtvcWsa4odBfp3zEwqtEgRUE2Pq1RobZXhJxviPiIYt+6X +wBtqbLjiiDTfgeZsKfqmdqJogngnA0fzthCOKHI81KObzoS2rniVzy5291aJC2oeKTd vSrj4zj73jFO0F56s9I0pMvIW7r9uu8uWzU3XlgXhJKVpmXhauObwl9HnNB3Rgz6e7lB b74Qjjup9VSCsOMIusq//cfNXpiFIoI7owiASAqAuMbjVRa9C1SoRorLk7usXrqImpB1 dz1Q== X-Gm-Message-State: AOAM531ddm49rWscJ8EZUCqvZRsXwRdx1tLqrU8p0Wptv+jL2hxBmbFf ZIno4eDJ9rKxhHjDmgzu9b0= X-Google-Smtp-Source: ABdhPJyxSsTVc2hFaLOzlSxMKrrpHAaRh8LwmPwoEUd1hvuHBP8YbXnfPA8KhdBCWpIikWlD+4naxw== X-Received: by 2002:a17:902:a417:b0:158:ed2c:3740 with SMTP id p23-20020a170902a41700b00158ed2c3740mr7796553plq.121.1651920114698; Sat, 07 May 2022 03:41:54 -0700 (PDT) Received: from localhost (61-245-128-160.3df580.per.nbn.aussiebb.net. [61.245.128.160]) by smtp.gmail.com with ESMTPSA id r23-20020a632057000000b003c14af50615sm4914892pgm.45.2022.05.07.03.41.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 May 2022 03:41:54 -0700 (PDT) From: Timothy To: Ihor Radchenko Cc: emacs-orgmode@gnu.org, Daniel Fleischer , Nicolas Goaziou Subject: Re: [PATCH] New LaTeX code export option: engraved Date: Sat, 07 May 2022 18:40:25 +0800 References: <87wnf1z1w8.fsf@gmail.com> <87sfpogyag.fsf@localhost> <87v8ukyo94.fsf@gmail.com> <87sfpoyn0l.fsf@gmail.com> <875ymhzzvq.fsf@localhost> <87o809n7hw.fsf@gmail.com> User-agent: mu4e 1.6.10; emacs 28.0.92 In-reply-to: <87o809n7hw.fsf@gmail.com> Message-ID: <87mtftmxox.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2607:f8b0:4864:20::630; envelope-from=tecosaur@gmail.com; helo=mail-pl1-x630.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1651920288; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=Q692dtr9Q9/0EyIR2oXijira7tR5TSZl530D8dtro9c=; b=oXbeIMROVF8oXkxT1k9XV0h7Uz5DFkeXa7J9PCqs7ZIhbQHcbRstNYA72gKg6ELou4xFZr aepiSJCGDmds3ld5QZ57DoxMNiPdkTVJ3F4roaiaWm1atxLwboMqJC3/SJ/x85DSu/B9fq KOoA/pLk8jzP0perN+OM+YtdZToTSB+BXALh7FXoAx+ozAhAPt5vvecxKO9Y9n9hFUaYKA GMe96Tjq1Au/S/3QXhiAdQss2tEzsG6v7bWolDs0D3HvfQLWlhG9r6rV6rsNy61gTJhHQL Nkmi6uEKBuxck6nF112BJTWuvRey8ipr5fd/89YUpYEllQmAifdfHe0Aw1vsLw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1651920288; a=rsa-sha256; cv=none; b=tphUQBieuR9pd78YwwowAbtfGDpR29ihCZPIwej+nVuWduFcZfx+7jXa2TfipzN0mX24K6 ZP9SI6gMICi7Ir5crYa0wB/vRkG+RhWKigEDrRcoXR9aPC3qnI16/vAZ2YOSOYoVyFIhnm 565u3f7Xef/7uZ9iKahsQrJ8WzIuCSX4HYTpRMNxAZYCMh0xFeYAmxevsL0fjnf9uMZG18 LiWZDt635l2CTB5hjj3dgR1hAi0LVPZjWXhLc11gDuxgITRCKue0nA0w8+6JBvaZgOaiBj wpO1jXI6w8ECRtccQ//hiqmlQQ0UCj/PBpMf853DBo/duMm2q1+UxqyopZ9aSg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20210112 header.b="l2IB/5RG"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: 6.40 Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20210112 header.b="l2IB/5RG"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: E41A622285 X-Spam-Score: 6.40 X-Migadu-Scanner: scn0.migadu.com X-TUID: s5XwKYiOl8Un --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Ooops, a paren error managed to slip in there. Here=E2=80=99s a new set, with a little extra refactoring slipped in. =E2=80=93 Timothy --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-ox-latex-Refactor-org-latex-src-block.patch >From d231437e2c9f96bf70520d9ddda810a95667fcdd Mon Sep 17 00:00:00 2001 From: TEC Date: Sun, 21 Nov 2021 14:35:34 +0800 Subject: [PATCH 1/7] ox-latex: Refactor `org-latex-src-block' * lisp/ox-latex.el (org-latex-src-block): Extract the per-format logic from `org-latex-src-block' into new dedicated functions: + `org-latex-src-block--verbatim' + `org-latex-src-block--custom' + `org-latex-src-block--minted' + `org-latex-src-block--listings' This makes `org-latex-src-block' much less monolithic, taking it from 175 lines to 30, and I find also makes it easier to understand. --- lisp/ox-latex.el | 339 ++++++++++++++++++++++++++--------------------- 1 file changed, 185 insertions(+), 154 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 841ad48bc..c2f728a1c 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -2997,164 +2997,195 @@ (defun org-latex-src-block (src-block _contents info) (float (plist-get attributes :float)) (listings (plist-get info :latex-listings))) (cond - ;; Case 1. No source fontification. ((or (not lang) (not listings)) - (let ((caption-str (org-latex--caption/label-string src-block info)) - (verbatim (format "\\begin{verbatim}\n%s\\end{verbatim}" - (org-export-format-code-default src-block info)))) - (cond ((string= "multicolumn" float) - (format "\\begin{figure*}[%s]\n%s%s\n%s\\end{figure*}" - (plist-get info :latex-default-figure-position) - (if caption-above-p caption-str "") - verbatim - (if caption-above-p "" caption-str))) - (caption (concat - (if caption-above-p caption-str "") - verbatim - (if caption-above-p "" (concat "\n" caption-str)))) - (t verbatim)))) - ;; Case 2. Custom environment. + (org-latex-src-block--verbatim src-block info lang caption caption-above-p label + num-start retain-labels attributes float)) (custom-env - (let ((caption-str (org-latex--caption/label-string src-block info)) - (formatted-src (org-export-format-code-default src-block info))) - (if (string-match-p "\\`[a-zA-Z0-9]+\\'" custom-env) - (format "\\begin{%s}\n%s\\end{%s}\n" - custom-env - (concat (and caption-above-p caption-str) - formatted-src - (and (not caption-above-p) caption-str)) - custom-env) - (format-spec custom-env - `((?s . ,formatted-src) - (?c . ,caption) - (?f . ,float) - (?l . ,(org-latex--label src-block info)) - (?o . ,(or (plist-get attributes :options) ""))))))) - ;; Case 3. Use minted package. + (org-latex-src-block--custom src-block info lang caption caption-above-p label + num-start retain-labels attributes float custom-env)) ((eq listings 'minted) - (let* ((caption-str (org-latex--caption/label-string src-block info)) - (placement (or (org-unbracket-string "[" "]" (plist-get attributes :placement)) - (plist-get info :latex-default-figure-position))) - (float-env - (cond - ((string= "multicolumn" float) - (format "\\begin{listing*}[%s]\n%s%%s\n%s\\end{listing*}" - placement - (if caption-above-p caption-str "") - (if caption-above-p "" caption-str))) - (caption - (format "\\begin{listing}[%s]\n%s%%s\n%s\\end{listing}" - placement - (if caption-above-p caption-str "") - (if caption-above-p "" caption-str))) - ((string= "t" float) - (concat (format "\\begin{listing}[%s]\n" - placement) - "%s\n\\end{listing}")) - (t "%s"))) - (options (plist-get info :latex-minted-options)) - (body - (format - "\\begin{minted}[%s]{%s}\n%s\\end{minted}" - ;; Options. - (concat - (org-latex--make-option-string - (if (or (not num-start) (assoc "linenos" options)) - options - (append - `(("linenos") - ("firstnumber" ,(number-to-string (1+ num-start)))) - options))) - (let ((local-options (plist-get attributes :options))) - (and local-options (concat "," local-options)))) - ;; Language. - (or (cadr (assq (intern lang) - (plist-get info :latex-minted-langs))) - (downcase lang)) - ;; Source code. - (let* ((code-info (org-export-unravel-code src-block)) - (max-width - (apply 'max - (mapcar 'length - (org-split-string (car code-info) - "\n"))))) - (org-export-format-code - (car code-info) - (lambda (loc _num ref) - (concat - loc - (when ref - ;; Ensure references are flushed to the right, - ;; separated with 6 spaces from the widest line - ;; of code. - (concat (make-string (+ (- max-width (length loc)) 6) - ?\s) - (format "(%s)" ref))))) - nil (and retain-labels (cdr code-info))))))) - ;; Return value. - (format float-env body))) - ;; Case 4. Use listings package. + (org-latex-src-block--minted src-block info lang caption caption-above-p label + num-start retain-labels attributes float)) (t - (let ((lst-lang - (or (cadr (assq (intern lang) - (plist-get info :latex-listings-langs))) - lang)) - (caption-str - (when caption - (let ((main (org-export-get-caption src-block)) - (secondary (org-export-get-caption src-block t))) - (if (not secondary) - (format "{%s}" (org-export-data main info)) - (format "{[%s]%s}" - (org-export-data secondary info) - (org-export-data main info)))))) - (lst-opt (plist-get info :latex-listings-options))) - (concat - ;; Options. - (format - "\\lstset{%s}\n" - (concat - (org-latex--make-option-string - (append - lst-opt - (cond - ((and (not float) (plist-member attributes :float)) nil) - ((string= "multicolumn" float) '(("float" "*"))) - ((and float (not (assoc "float" lst-opt))) - `(("float" ,(plist-get info :latex-default-figure-position))))) - `(("language" ,lst-lang)) - (if label - `(("label" ,(org-latex--label src-block info))) - '(("label" " "))) - (if caption-str `(("caption" ,caption-str)) '(("caption" " "))) - `(("captionpos" ,(if caption-above-p "t" "b"))) - (cond ((assoc "numbers" lst-opt) nil) - ((not num-start) '(("numbers" "none"))) - (t `(("firstnumber" ,(number-to-string (1+ num-start))) - ("numbers" "left")))))) - (let ((local-options (plist-get attributes :options))) - (and local-options (concat "," local-options))))) - ;; Source code. - (format - "\\begin{lstlisting}\n%s\\end{lstlisting}" - (let* ((code-info (org-export-unravel-code src-block)) - (max-width - (apply 'max - (mapcar 'length - (org-split-string (car code-info) "\n"))))) - (org-export-format-code - (car code-info) - (lambda (loc _num ref) - (concat - loc - (when ref - ;; Ensure references are flushed to the right, - ;; separated with 6 spaces from the widest line of - ;; code - (concat (make-string (+ (- max-width (length loc)) 6) ?\s) - (format "(%s)" ref))))) - nil (and retain-labels (cdr code-info)))))))))))) - + (org-latex-src-block--listings src-block info lang caption caption-above-p label + num-start retain-labels attributes float)))))) + +(defun org-latex-src-block--verbatim + (src-block info _lang caption caption-above-p _label + _num-start _retain-labels _attributes float) + "Transcode a SRC-BLOCK element from Org to LaTeX, using verbatim. +LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES +and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." + (let ((caption-str (org-latex--caption/label-string src-block info)) + (verbatim (format "\\begin{verbatim}\n%s\\end{verbatim}" + (org-export-format-code-default src-block info)))) + (cond ((string= "multicolumn" float) + (format "\\begin{figure*}[%s]\n%s%s\n%s\\end{figure*}" + (plist-get info :latex-default-figure-position) + (if caption-above-p caption-str "") + verbatim + (if caption-above-p "" caption-str))) + (caption (concat + (if caption-above-p caption-str "") + verbatim + (if caption-above-p "" (concat "\n" caption-str)))) + (t verbatim)))) + +(defun org-latex-src-block--custom + (src-block info _lang caption caption-above-p _label + _num-start _retain-labels attributes float custom-env) + "Transcode a SRC-BLOCK element from Org to LaTeX, using a custom environment. +LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES +and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." + (let ((caption-str (org-latex--caption/label-string src-block info)) + (formatted-src (org-export-format-code-default src-block info))) + (if (string-match-p "\\`[a-zA-Z0-9]+\\'" custom-env) + (format "\\begin{%s}\n%s\\end{%s}\n" + custom-env + (concat (and caption-above-p caption-str) + formatted-src + (and (not caption-above-p) caption-str)) + custom-env) + (format-spec custom-env + `((?s . ,formatted-src) + (?c . ,caption) + (?f . ,float) + (?l . ,(org-latex--label src-block info)) + (?o . ,(or (plist-get attributes :options) ""))))))) + +(defun org-latex-src-block--minted + (src-block info lang caption caption-above-p _label + num-start retain-labels attributes float) + "Transcode a SRC-BLOCK element from Org to LaTeX, using minted. +LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES +and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." + (let* ((caption-str (org-latex--caption/label-string src-block info)) + (placement (or (org-unbracket-string "[" "]" (plist-get attributes :placement)) + (plist-get info :latex-default-figure-position))) + (float-env + (cond + ((string= "multicolumn" float) + (format "\\begin{listing*}[%s]\n%s%%s\n%s\\end{listing*}" + placement + (if caption-above-p caption-str "") + (if caption-above-p "" caption-str))) + (caption + (format "\\begin{listing}[%s]\n%s%%s\n%s\\end{listing}" + placement + (if caption-above-p caption-str "") + (if caption-above-p "" caption-str))) + ((string= "t" float) + (concat (format "\\begin{listing}[%s]\n" + placement) + "%s\n\\end{listing}")) + (t "%s"))) + (options (plist-get info :latex-minted-options)) + (body + (format + "\\begin{minted}[%s]{%s}\n%s\\end{minted}" + ;; Options. + (concat + (org-latex--make-option-string + (if (or (not num-start) (assoc "linenos" options)) + options + (append + `(("linenos") + ("firstnumber" ,(number-to-string (1+ num-start)))) + options))) + (let ((local-options (plist-get attributes :options))) + (and local-options (concat "," local-options)))) + ;; Language. + (or (cadr (assq (intern lang) + (plist-get info :latex-minted-langs))) + (downcase lang)) + ;; Source code. + (let* ((code-info (org-export-unravel-code src-block)) + (max-width + (apply 'max + (mapcar 'length + (org-split-string (car code-info) + "\n"))))) + (org-export-format-code + (car code-info) + (lambda (loc _num ref) + (concat + loc + (when ref + ;; Ensure references are flushed to the right, + ;; separated with 6 spaces from the widest line + ;; of code. + (concat (make-string (+ (- max-width (length loc)) 6) + ?\s) + (format "(%s)" ref))))) + nil (and retain-labels (cdr code-info))))))) + ;; Return value. + (format float-env body))) + +(defun org-latex-src-block--listings + (src-block info lang caption caption-above-p label + num-start retain-labels attributes float) + "Transcode a SRC-BLOCK element from Org to LaTeX, using listings. +LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES +and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." + (let ((lst-lang + (or (cadr (assq (intern lang) + (plist-get info :latex-listings-langs))) + lang)) + (caption-str + (when caption + (let ((main (org-export-get-caption src-block)) + (secondary (org-export-get-caption src-block t))) + (if (not secondary) + (format "{%s}" (org-export-data main info)) + (format "{[%s]%s}" + (org-export-data secondary info) + (org-export-data main info)))))) + (lst-opt (plist-get info :latex-listings-options))) + (concat + ;; Options. + (format + "\\lstset{%s}\n" + (concat + (org-latex--make-option-string + (append + lst-opt + (cond + ((and (not float) (plist-member attributes :float)) nil) + ((string= "multicolumn" float) '(("float" "*"))) + ((and float (not (assoc "float" lst-opt))) + `(("float" ,(plist-get info :latex-default-figure-position))))) + `(("language" ,lst-lang)) + (if label + `(("label" ,(org-latex--label src-block info))) + '(("label" " "))) + (if caption-str `(("caption" ,caption-str)) '(("caption" " "))) + `(("captionpos" ,(if caption-above-p "t" "b"))) + (cond ((assoc "numbers" lst-opt) nil) + ((not num-start) '(("numbers" "none"))) + (t `(("firstnumber" ,(number-to-string (1+ num-start))) + ("numbers" "left")))))) + (let ((local-options (plist-get attributes :options))) + (and local-options (concat "," local-options))))) + ;; Source code. + (format + "\\begin{lstlisting}\n%s\\end{lstlisting}" + (let* ((code-info (org-export-unravel-code src-block)) + (max-width + (apply 'max + (mapcar 'length + (org-split-string (car code-info) "\n"))))) + (org-export-format-code + (car code-info) + (lambda (loc _num ref) + (concat + loc + (when ref + ;; Ensure references are flushed to the right, + ;; separated with 6 spaces from the widest line of + ;; code + (concat (make-string (+ (- max-width (length loc)) 6) ?\s) + (format "(%s)" ref))))) + nil (and retain-labels (cdr code-info)))))))) ;;;; Statistics Cookie -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-ox-latex-Refactor-org-latex-inline-src-block.patch >From aa8406ce64507b870322495e8f9b54317930ed24 Mon Sep 17 00:00:00 2001 From: TEC Date: Wed, 4 May 2022 18:53:10 +0800 Subject: [PATCH 2/7] ox-latex: Refactor `org-latex-inline-src-block' * lisp/ox-latex.el (org-latex-inline-src-block, org-latex-inline-src-block--minted, org-latex-inline-src-block--listings): Extract the minted and listings specific logic out of `org-latex-inline-src-block` into the new functions `org-latex-inline-src-block--minted` and `org-latex-inline-src-block--listings`. --- lisp/ox-latex.el | 62 +++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index c2f728a1c..38f36a1f3 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -2127,36 +2127,38 @@ (defun org-latex-inline-src-block (inline-src-block _contents info) "Transcode an INLINE-SRC-BLOCK element from Org to LaTeX. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (let* ((code (org-element-property :value inline-src-block)) - (separator (org-latex--find-verb-separator code))) - (cl-case (plist-get info :latex-listings) - ;; Do not use a special package: transcode it verbatim, as code. - ((nil) (org-latex--text-markup code 'code info)) - ;; Use minted package. - (minted - (let* ((org-lang (org-element-property :language inline-src-block)) - (mint-lang (or (cadr (assq (intern org-lang) - (plist-get info :latex-minted-langs))) - (downcase org-lang))) - (options (org-latex--make-option-string - (plist-get info :latex-minted-options)))) - (format "\\mintinline%s{%s}{%s}" - (if (string= options "") "" (format "[%s]" options)) - mint-lang - code))) - ;; Use listings package. - (otherwise - ;; Maybe translate language's name. - (let* ((org-lang (org-element-property :language inline-src-block)) - (lst-lang (or (cadr (assq (intern org-lang) - (plist-get info :latex-listings-langs))) - org-lang)) - (options (org-latex--make-option-string - (append (plist-get info :latex-listings-options) - `(("language" ,lst-lang)))))) - (concat (format "\\lstinline[%s]" options) - separator code separator)))))) - + (let ((code (org-element-property :value inline-src-block)) + (lang (org-element-property :language inline-src-block))) + (pcase (plist-get info :latex-listings) + ('nil (org-latex--text-markup code 'code info)) + ('minted (org-latex-inline-src-block--minted info code lang)) + (_ (org-latex-inline-src-block--listings info code lang))))) + +(defun org-latex-inline-src-block--minted (info code lang) + "Transcode an inline src block's content from Org to LaTeX, using minted. +INFO, CODE, and LANG are provided by `org-latex-inline-src-block'." + (let ((mint-lang (or (cadr (assq (intern lang) + (plist-get info :latex-minted-langs))) + (downcase lang))) + (options (org-latex--make-option-string + (plist-get info :latex-minted-options)))) + (format "\\mintinline%s{%s}{%s}" + (if (string= options "") "" (format "[%s]" options)) + mint-lang + code))) + +(defun org-latex-inline-src-block--listings (info code lang) + "Transcode an inline src block's content from Org to LaTeX, using lstlistings. +INFO, CODE, and LANG are provided by `org-latex-inline-src-block'." + (let* ((lst-lang (or (cadr (assq (intern lang) + (plist-get info :latex-listings-langs))) + lang)) + (separator (org-latex--find-verb-separator code)) + (options (org-latex--make-option-string + (append (plist-get info :latex-listings-options) + `(("language" ,lst-lang)))))) + (concat (format "\\lstinline[%s]" options) + separator code separator))) ;;;; Inlinetask -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-ox-latex-More-versitile-option-construction.patch >From 62d6703f0dd622916dff8aab960db6df4cb58cf7 Mon Sep 17 00:00:00 2001 From: TEC Date: Wed, 4 May 2022 23:31:59 +0800 Subject: [PATCH 3/7] ox-latex: More versitile option construction * lisp/ox-latex.el (org-latex--make-option-string): Support a custom option seperator string. (org-latex--make-option-string, org-latex-minted-options, org-latex-listings-options): The first line of the docstrings for `org-latex-minted-options` and `org-latex-listings-options` describe the variables as "association lists", yet `org-latex--make-option-string` does not handle association lists and an example of two-value lists is provided. To make the behaviour match the docstring, `org-latex--make-option-string` is modified to work with either a list two-value lists or an association list, and the examples in `org-latex-minted-options` and `org-latex-listings-options` updated accordingly. --- lisp/ox-latex.el | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 38f36a1f3..2d4b3bace 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1006,12 +1006,16 @@ (defcustom org-latex-listings-options nil These options are supplied as a comma-separated list to the \\lstset command. Each element of the association list should be -a list containing two strings: the name of the option, and the -value. For example, +a list or cons cell containing two strings: the name of the +option, and the value. For example, (setq org-latex-listings-options \\='((\"basicstyle\" \"\\\\small\") (\"keywordstyle\" \"\\\\color{black}\\\\bfseries\\\\underbar\"))) + ; or + (setq org-latex-listings-options + \\='((\"basicstyle\" . \"\\\\small\") + (\"keywordstyle\" . \"\\\\color{black}\\\\bfseries\\\\underbar\"))) will typeset the code in a small size font with underlined, bold black keywords. @@ -1059,11 +1063,14 @@ (defcustom org-latex-minted-options nil These options are supplied within square brackets in \\begin{minted} environments. Each element of the alist should -be a list containing two strings: the name of the option, and the -value. For example, +be a list or cons cell containing two strings: the name of the +option, and the value. For example, (setq org-latex-minted-options \\='((\"bgcolor\" \"bg\") (\"frame\" \"lines\"))) + ; or + (setq org-latex-minted-options + \\='((\"bgcolor\" . \"bg\") (\"frame\" . \"lines\"))) will result in source blocks being exported with @@ -1506,21 +1513,24 @@ (defun org-latex--find-verb-separator (s) when (not (string-match (regexp-quote (char-to-string c)) s)) return (char-to-string c)))) -(defun org-latex--make-option-string (options) +(defun org-latex--make-option-string (options &optional seperator) "Return a comma separated string of keywords and values. OPTIONS is an alist where the key is the options keyword as a string, and the value a list containing the keyword value, or nil." (mapconcat (lambda (pair) - (pcase-let ((`(,keyword ,value) pair)) - (concat keyword - (and (> (length value) 0) - (concat "=" - (if (string-match-p (rx (any "[]")) value) - (format "{%s}" value) - value)))))) - options - ",")) + (let ((keyword (car pair)) + (value (pcase (cdr pair) + ((pred stringp) (cdr pair)) + ((pred consp) (cadr pair))))) + (concat keyword + (when value + (concat "=" + (if (string-match-p (rx (any "[]")) value) + (format "{%s}" value) + value)))))) + options + (or seperator ","))) (defun org-latex--wrap-label (element output info) "Wrap label associated to ELEMENT around OUTPUT, if appropriate. -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-ox-latex-Introduce-engraved-code-highlighting.patch >From 81155a80fb261812718dcb991fd22f87bb1d5ef6 Mon Sep 17 00:00:00 2001 From: TEC Date: Sun, 21 Nov 2021 20:04:12 +0800 Subject: [PATCH 4/7] ox-latex: Introduce "engraved" code highlighting * lisp/ox-latex.el (org-latex-src-block, org-latex-src-block--engraved, org-latex-inline-src-block, org-latex-inline-src-block--engraved, org-latex-src--engrave-code, org-latex-template, org-latex-listings): Make use of the engraved-faces package (available on ELPA) to provide an alternative LaTeX code highlighting backend which functions similarly to htmlize.el for HTML exports. (org-latex-engraved-preamble, org-latex-engraved-options): Introduce variables to construct the preamble for engraved code blocks. * lisp/ox-beamer.el (org-beamer-template): Modify to add engrave-faces preamble when applicable. tweak --- lisp/ox-beamer.el | 11 ++ lisp/ox-latex.el | 272 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 274 insertions(+), 9 deletions(-) diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el index 6be73c91e..4d40f6a1d 100644 --- a/lisp/ox-beamer.el +++ b/lisp/ox-beamer.el @@ -857,6 +857,17 @@ (defun org-beamer-template (contents info) (let ((template (plist-get info :latex-hyperref-template))) (and (stringp template) (format-spec template (org-latex--format-spec info)))) + ;; engrave-faces-latex preamble + (when (eq org-latex-listings 'engraved) + (let ((src-p (org-element-map (plist-get info :parse-tree) + '(src-block inline-src-block) #'identity + info t)) + (fixedw-p + (org-element-map (plist-get info :parse-tree) + '(example-block fixed-width) #'identity + info t))) + (when (or src-p fixedw-p) + (org-latex-generate-engraved-preamble info src-p)))) ;; Document start. "\\begin{document}\n\n" ;; Title command. diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 2d4b3bace..10cd6d76d 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -37,6 +37,8 @@ (defvar org-latex-default-packages-alist) (defvar org-latex-packages-alist) (defvar orgtbl-exp-regexp) +(declare-function engrave-faces-latex-gen-preamble "ext:engrave-faces-latex") +(declare-function engrave-faces-latex-buffer "ext:engrave-faces-latex") ;;; Define Back-End @@ -125,6 +127,8 @@ (org-export-define-backend 'latex (:latex-default-quote-environment nil nil org-latex-default-quote-environment) (:latex-default-table-mode nil nil org-latex-default-table-mode) (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format) + (:latex-engraved-options nil nil org-latex-engraved-options) + (:latex-engraved-preamble nil nil org-latex-engraved-preamble) (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format) (:latex-footnote-separator nil nil org-latex-footnote-separator) (:latex-format-drawer-function nil nil org-latex-format-drawer-function) @@ -937,22 +941,48 @@ (defcustom org-latex-listings nil "Non-nil means export source code using the listings package. This package will fontify source code, possibly even with color. -If you want to use this, you also need to make LaTeX use the -listings package, and if you want to have color, the color -package. Just add these to `org-latex-packages-alist', for -example using customize, or with something like: +There are four implementations of this functionality you may +choose from (ordered from least to most capable): +1. Verbatim (nil) +2. Listings (t) +3. Minted (minted) +4. Engraved (engraved) + +The first two options provide basic syntax +highlighting (listings), or none at all (verbatim). + +When using listings, you also need to make use of the LaTeX +\"listings\" package. The \"color\" package is also needed if you +would like color too. These can simply be added to +`org-latex-packages-alist', using customise or something like: (require \\='ox-latex) (add-to-list \\='org-latex-packages-alist \\='(\"\" \"listings\")) (add-to-list \\='org-latex-packages-alist \\='(\"\" \"color\")) -Alternatively, +There are two further options for more comprehensive +fontification. The first can be set with, + + (setq org-latex-listings \\='engraved) + +which causes source code to be run through +`engrave-faces-latex-buffer', which generates colorings using +Emacs' font-lock information. This requires the engrave-faces +package (availible from ELPA), and the fvextra LaTeX package be +installed. + +The styling of the engraved result can customised with +`org-latex-engraved-preamble' and `org-latex-engraved-options'. +The default preamble also uses the tcolorbox LaTeX package in +addition to fvextra. + +The second more comprehensive option can be set with, (setq org-latex-listings \\='minted) -causes source code to be exported using the minted package as -opposed to listings. If you want to use minted, you need to add -the minted package to `org-latex-packages-alist', for example +which causes source code to be exported using the minted package +as opposed to listings. If you want to use minted, you need to +add the minted package to `org-latex-packages-alist', for example using customize, or with (require \\='ox-latex) @@ -971,8 +1001,9 @@ (defcustom org-latex-listings nil :type '(choice (const :tag "Use listings" t) (const :tag "Use minted" minted) + (const :tag "Use engrave-faces-latex" engraved) (const :tag "Export verbatim" nil)) - :safe (lambda (s) (memq s '(t nil minted)))) + :safe (lambda (s) (memq s '(t nil minted engraved)))) (defcustom org-latex-listings-langs '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp") @@ -1142,6 +1173,127 @@ (defcustom org-latex-custom-lang-environments nil :version "26.1" :package-version '(Org . "9.0")) +(defcustom org-latex-engraved-preamble + "\\usepackage{fvextra} + +[FVEXTRA-SETUP] + +% Make line numbers smaller and grey. +\\renewcommand\\theFancyVerbLine{\\footnotesize\\color{black!40!white}\\arabic{FancyVerbLine}} + +\\usepackage{xcolor} + +\\providecolor{codebackground}{HTML}{f7f7f7} +\\providecolor{codeborder}{HTML}{f0f0f0} +\\providecolor{EFD}{HTML}{28292e} + +% Define a Code environment to prettily wrap the fontified code. +\\usepackage[breakable,xparse]{tcolorbox} +\\DeclareTColorBox[]{Code}{o}% +{colback=codebackground, colframe=codeborder, + fontupper=\\footnotesize\\setlength{\\fboxsep}{0pt}, + colupper=EFD, + IfNoValueTF={#1}% + {boxsep=2pt, arc=2.5pt, outer arc=2.5pt, + boxrule=0.5pt, left=2pt}% + {boxsep=2.5pt, arc=0pt, outer arc=0pt, + boxrule=0pt, leftrule=1.5pt, left=0.5pt}, + right=2pt, top=1pt, bottom=0.5pt, + breakable}" + "Preamble content injected when using engrave-faces-latex for source blocks. +This is relevant when `org-latex-listings' is set to `engraved'. + +There is quite a lot of flexibility in what this preamble can be, as long as it: +- Loads the fvextra package. +- Loads the package xcolor (if it is not already loader elsewhere). +- Defines a \"Code\" environment (note the capital C), which all + \"Verbatim\" environments (provided by fvextra) will be wrapped with. + +A macro-like placeholder is used to set fvextra's defaults according to +`org-latex-engraved-options': + + [FVEXTRA-SETUP] + +In the default value the color \"EFD\" is provided as this is the +foreground colour provided by engrave-faces-latex. When there +are example/fixed-width blocks only, the engraved generated +preamble is not included, and so it is provided so we may use it +anyway." + :group 'org-export-latex + :type 'string + :package-version '(Org . "9.6")) + +(defcustom org-latex-engraved-options + '(("commandchars" . "\\\\\\{\\}") + ("highlightcolor" . "white!95!black!80!blue") + ("breaklines" . "true") + ("breaksymbol" . "\\color{white!60!black}\\tiny\\ensuremath{\\hookrightarrow}")) + "Association list of options for the latex fvextra package when engraving code. + +These options are set using \\fvset{...} in the preamble of the +LaTeX export. Each element of the alist should be a list or cons +cell containing two strings: the name of the option, and the +value. For example, + + (setq org-latex-engraved-options + \\='((\"highlightcolor\" \"green\") (\"frame\" \"lines\"))) + ; or + (setq org-latex-engraved-options + \\='((\"highlightcolor\" . \"green\") (\"frame\" . \"lines\"))) + +will result in the following LaTeX in the preamble + +\\fvset{% + bgcolor=bg, + frame=lines} + +This will affect all fvextra environments. Note that the same +options will be applied to all blocks. If you need +block-specific options, you may use the following syntax: + + #+ATTR_LATEX: :options key1=value1,key2=value2 + #+BEGIN_SRC + ... + #+END_SRC" + :group 'org-export-latex + :type '(alist :key-type (string :tag "option") + :value-type (string :tag "value"))) + +(defun org-latex-generate-engraved-preamble (info syntax-colours-p) + "Generate the preamble to setup engraved code. +The result is constructed from the :latex-engraved-preamble and +:latex-engraved-optionsn export options, the default values of +which are given by `org-latex-engraved-preamble' and +`org-latex-engraved-options' respectively." + (let* ((engraved-options + (plist-get info :latex-engraved-options)) + (engraved-preamble-template + (plist-get info :latex-engraved-preamble)) + (engraved-preamble + (if (string-match "^[ \t]*\\[FVEXTRA-SETUP\\][ \t]*\n?" + engraved-preamble-template) + (replace-match + (concat + "\\fvset{%\n " + (org-latex--make-option-string engraved-options ",\n ") + "}\n") + t t + engraved-preamble-template) + engraved-preamble-template))) + (if 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" + (if (require 'engrave-faces-latex nil t) + (engrave-faces-latex-gen-preamble) + (message "Cannot engrave source blocks. Consider installing `engrave-faces'.") + "% WARNING syntax highlighting unavailible as engrave-faces-latex was missing.\n") + "\n") + (concat + "\n% Setup for code blocks\n\n" + engraved-preamble + "\n")))) ;;;; Compilation @@ -1756,6 +1908,17 @@ (defun org-latex-template (contents info) (let ((template (plist-get info :latex-hyperref-template))) (and (stringp template) (format-spec template spec))) + ;; engrave-faces-latex preamble + (when (eq org-latex-listings 'engraved) + (let ((src-p (org-element-map (plist-get info :parse-tree) + '(src-block inline-src-block) #'identity + info t)) + (fixedw-p + (org-element-map (plist-get info :parse-tree) + '(example-block fixed-width) #'identity + info t))) + (when (or src-p fixedw-p) + (org-latex-generate-engraved-preamble info src-p)))) ;; Document start. "\\begin{document}\n\n" ;; Title command. @@ -2142,6 +2305,7 @@ (defun org-latex-inline-src-block (inline-src-block _contents info) (pcase (plist-get info :latex-listings) ('nil (org-latex--text-markup code 'code info)) ('minted (org-latex-inline-src-block--minted info code lang)) + ('engraved (org-latex-inline-src-block--engraved info code lang)) (_ (org-latex-inline-src-block--listings info code lang))))) (defun org-latex-inline-src-block--minted (info code lang) @@ -2157,6 +2321,11 @@ (defun org-latex-inline-src-block--minted (info code lang) mint-lang code))) +(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))) + (defun org-latex-inline-src-block--listings (info code lang) "Transcode an inline src block's content from Org to LaTeX, using lstlistings. INFO, CODE, and LANG are provided by `org-latex-inline-src-block'." @@ -3017,6 +3186,9 @@ (defun org-latex-src-block (src-block _contents info) num-start retain-labels attributes float custom-env)) ((eq listings 'minted) (org-latex-src-block--minted src-block info lang caption caption-above-p label + num-start retain-labels attributes float)) + ((eq listings 'engraved) + (org-latex-src-block--engraved src-block info lang caption caption-above-p label num-start retain-labels attributes float)) (t (org-latex-src-block--listings src-block info lang caption caption-above-p label @@ -3133,6 +3305,88 @@ (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." + (if (require 'engrave-faces-latex nil t) + (let* ((lang-mode (and lang (org-src-get-lang-mode lang))) + (engraved-buffer + (with-temp-buffer + (insert content) + (when lang-mode + (if (functionp lang-mode) + (funcall lang-mode) + (message "Cannot engrave code as %s. %s is undefined." + lang lang-mode))) + (engrave-faces-latex-buffer))) + (engraved-code + (with-current-buffer engraved-buffer + (buffer-string)))) + (kill-buffer engraved-buffer) + engraved-code) + (user-error "Cannot engrave code as `engrave-faces-latex' is unavailible."))) + +(defun org-latex-src-block--engraved + (src-block info lang caption caption-above-p _label + num-start retain-labels attributes float) + "Transcode a SRC-BLOCK element from Org to LaTeX, using engrave-faces-latex. +LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES +and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." + (let* ((caption-str (org-latex--caption/label-string src-block info)) + (placement (or (org-unbracket-string "[" "]" (plist-get attributes :placement)) + (plist-get info :latex-default-figure-position))) + (float-env + (cond + ((string= "multicolumn" float) + (format "\\begin{listing*}[%s]\n%s%%s\n%s\\end{listing*}" + placement + (if caption-above-p caption-str "") + (if caption-above-p "" caption-str))) + (caption + (format "\\begin{listing}[%s]\n%s%%s\n%s\\end{listing}" + placement + (if caption-above-p caption-str "") + (if caption-above-p "" caption-str))) + ((string= "t" float) + (concat (format "\\begin{listing}[%s]\n" + placement) + "%s\n\\end{listing}")) + (t "%s"))) + (options (plist-get info :latex-engraved-options)) + (content + (let* ((code-info (org-export-unravel-code src-block)) + (max-width + (apply 'max + (mapcar 'string-width + (org-split-string (car code-info) + "\n"))))) + (org-export-format-code + (car code-info) + (lambda (loc _num ref) + (concat + loc + (when ref + ;; Ensure references are flushed to the right, + ;; separated with 6 spaces from the widest line + ;; of code. + (concat (make-string (+ (- max-width (length loc)) 6) + ?\s) + (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)))) + (format float-env body))) + (defun org-latex-src-block--listings (src-block info lang caption caption-above-p label num-start retain-labels attributes float) -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0005-ox-latex-Don-t-use-length-to-get-string-width.patch >From 96cf9853329dacd69745a225a889855dd13e5c2c Mon Sep 17 00:00:00 2001 From: TEC Date: Sat, 7 May 2022 13:59:13 +0800 Subject: [PATCH 5/7] ox-latex: Don't use `length' to get string width * lisp/ox-latex.el (org-latex-src-block--listings, org-latex-src-block--engraved, org-latex-src-block--minted): Use `string-width' instead of `length' to gauge the displayed width of the string in LaTeX. This may not be a perfect match, but it should be an improvement. --- lisp/ox-latex.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 10cd6d76d..afd7ee48e 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -3286,7 +3286,7 @@ (defun org-latex-src-block--minted (let* ((code-info (org-export-unravel-code src-block)) (max-width (apply 'max - (mapcar 'length + (mapcar 'string-width (org-split-string (car code-info) "\n"))))) (org-export-format-code @@ -3438,7 +3438,7 @@ (defun org-latex-src-block--listings (let* ((code-info (org-export-unravel-code src-block)) (max-width (apply 'max - (mapcar 'length + (mapcar 'string-width (org-split-string (car code-info) "\n"))))) (org-export-format-code (car code-info) -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0006-ox-latex-Refactor-source-block-transcode-fun-sigs.patch >From f191a03ef97f5f8e29b18b73238ab659709ae230 Mon Sep 17 00:00:00 2001 From: TEC Date: Sat, 7 May 2022 14:02:44 +0800 Subject: [PATCH 6/7] ox-latex: Refactor source block transcode fun sigs * lisp/ox-latex.el (org-latex-src-block--listings, org-latex-src-block--engraved, org-latex-src-block--minted, org-latex-src-block--custom): Refactor these --backend functions to use cl-defun with keys instead of having an 11-argument signature. (org-latex-src-block): Adjust for the change in signature of the --backend functions, and refactor the `cond' statement to use `pcase'. --- lisp/ox-latex.el | 82 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index afd7ee48e..9150c1011 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -3166,37 +3166,37 @@ (defun org-latex-src-block (src-block _contents info) contextual information." (when (org-string-nw-p (org-element-property :value src-block)) (let* ((lang (org-element-property :language src-block)) - (caption (org-element-property :caption src-block)) - (caption-above-p (org-latex--caption-above-p src-block info)) - (label (org-element-property :name src-block)) - (custom-env (and lang - (cadr (assq (intern lang) - org-latex-custom-lang-environments)))) - (num-start (org-export-get-loc src-block info)) - (retain-labels (org-element-property :retain-labels src-block)) - (attributes (org-export-read-attribute :attr_latex src-block)) - (float (plist-get attributes :float)) - (listings (plist-get info :latex-listings))) - (cond - ((or (not lang) (not listings)) - (org-latex-src-block--verbatim src-block info lang caption caption-above-p label - num-start retain-labels attributes float)) - (custom-env - (org-latex-src-block--custom src-block info lang caption caption-above-p label - num-start retain-labels attributes float custom-env)) - ((eq listings 'minted) - (org-latex-src-block--minted src-block info lang caption caption-above-p label - num-start retain-labels attributes float)) - ((eq listings 'engraved) - (org-latex-src-block--engraved src-block info lang caption caption-above-p label - num-start retain-labels attributes float)) - (t - (org-latex-src-block--listings src-block info lang caption caption-above-p label - num-start retain-labels attributes float)))))) - -(defun org-latex-src-block--verbatim - (src-block info _lang caption caption-above-p _label - _num-start _retain-labels _attributes float) + (caption (org-element-property :caption src-block)) + (caption-above-p (org-latex--caption-above-p src-block info)) + (label (org-element-property :name src-block)) + (custom-env (and lang + (cadr (assq (intern lang) + org-latex-custom-lang-environments)))) + (num-start (org-export-get-loc src-block info)) + (retain-labels (org-element-property :retain-labels src-block)) + (attributes (org-export-read-attribute :attr_latex src-block)) + (float (plist-get attributes :float)) + (listings (plist-get info :latex-listings))) + (funcall + (pcase listings + ((or (pred not) (guard (not lang))) #'org-latex-src-block--verbatim) + ((guard custom-env) #'org-latex-src-block--custom) + ('minted #'org-latex-src-block--minted) + ('engraved #'org-latex-src-block--engraved) + (_ #'org-latex-src-block--listings)) + :src-block src-block + :info info + :lang lang + :caption caption + :caption-above-p caption-above-p + :label label + :num-start num-start + :retain-labels retain-labels + :attributes attributes + :float float)))) + +(cl-defun org-latex-src-block--verbatim + (&key src-block info caption caption-above-p float &allow-other-keys) "Transcode a SRC-BLOCK element from Org to LaTeX, using verbatim. LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." @@ -3215,9 +3215,8 @@ (defun org-latex-src-block--verbatim (if caption-above-p "" (concat "\n" caption-str)))) (t verbatim)))) -(defun org-latex-src-block--custom - (src-block info _lang caption caption-above-p _label - _num-start _retain-labels attributes float custom-env) +(cl-defun org-latex-src-block--custom + (&key src-block info caption caption-above-p attributes float custom-env &allow-other-keys) "Transcode a SRC-BLOCK element from Org to LaTeX, using a custom environment. LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." @@ -3237,9 +3236,8 @@ (defun org-latex-src-block--custom (?l . ,(org-latex--label src-block info)) (?o . ,(or (plist-get attributes :options) ""))))))) -(defun org-latex-src-block--minted - (src-block info lang caption caption-above-p _label - num-start retain-labels attributes float) +(cl-defun org-latex-src-block--minted + (&key src-block info lang caption caption-above-p num-start retain-labels attributes float &allow-other-keys) "Transcode a SRC-BLOCK element from Org to LaTeX, using minted. LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." @@ -3325,9 +3323,8 @@ (defun org-latex-src--engrave-code (content lang) engraved-code) (user-error "Cannot engrave code as `engrave-faces-latex' is unavailible."))) -(defun org-latex-src-block--engraved - (src-block info lang caption caption-above-p _label - num-start retain-labels attributes float) +(cl-defun org-latex-src-block--engraved + (&key src-block info lang caption caption-above-p num-start retain-labels attributes float &allow-other-keys) "Transcode a SRC-BLOCK element from Org to LaTeX, using engrave-faces-latex. LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." @@ -3387,9 +3384,8 @@ (defun org-latex-src-block--engraved (org-latex-src--engrave-code content lang)))) (format float-env body))) -(defun org-latex-src-block--listings - (src-block info lang caption caption-above-p label - num-start retain-labels attributes float) +(cl-defun org-latex-src-block--listings + (&key src-block info lang caption caption-above-p label num-start retain-labels attributes float &allow-other-keys) "Transcode a SRC-BLOCK element from Org to LaTeX, using listings. LANG, CAPTION, CAPTION-ABOVE-P, LABEL, NUM-START, RETAIN-LABELS, ATTRIBUTES and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." -- 2.35.3 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0007-ox-latex-Replace-org-latex-listings.patch >From adb4b6df3b4549fd6afd6cfb6ae8945e89882cfc Mon Sep 17 00:00:00 2001 From: TEC Date: Sat, 7 May 2022 14:46:28 +0800 Subject: [PATCH 7/7] ox-latex: Replace `org-latex-listings' * lisp/ox-latex.el (org-latex-src-block, org-latex-keyword, org-latex-inline-src-block, org-latex-template, org-latex--caption/label-string, org-latex-engraved-preamble, org-latex-listings): Replace `org-latex-listings' with `org-latex-src-block-backend', which now can be set to listings/verbatim and no longer advertises t/nil as valid values. * lisp/ox-beamer.el (org-beamer-template): Update in the same manner as `org-latex-template'. * lisp/org-compat.el: Make `org-latex-listings' an obsolete alias for `org-latex-src-block-backend'. * testing/lisp/test-ox.el: Replace `org-latex-listings' reference with `org-latex-src-block-backend'. * doc/org-manual.org (Footnotes, LaTeX specific properties, Literal Examples): Replace references to `org-latex-listings' with `org-latex-src-block-backend'. * etc/ORG-NEWS: Add a news entry noting this change. The variable `org-latex-listings' originally indicated whether source blocks should use the listings LaTeX package, or not. This usage has evolved over the years, and now it sets one of four different fontification backends. This renaming should make the variable name a bit less misleading. --- doc/org-manual.org | 6 +-- etc/ORG-NEWS | 9 ++++ lisp/org-compat.el | 2 + lisp/ox-beamer.el | 2 +- lisp/ox-latex.el | 111 ++++++++++++++++++++++------------------ testing/lisp/test-ox.el | 2 +- 6 files changed, 78 insertions(+), 54 deletions(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index c0d38cd8c..60bded419 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -11159,7 +11159,7 @@ ** Literal Examples #+end_example #+cindex: formatting source code, markup rules -#+vindex: org-latex-listings +#+vindex: org-latex-src-block-backend If the example is source code from a programming language, or any other text that can be marked up by Font Lock in Emacs, you can ask for the example to look like the fontified Emacs buffer[fn:114]. This @@ -16304,12 +16304,12 @@ **** LaTeX specific properties | ~:latex-link-with-unknown-path-format~ | ~org-latex-link-with-unknown-path-format~ | | ~:latex-listings-langs~ | ~org-latex-listings-langs~ | | ~:latex-listings-options~ | ~org-latex-listings-options~ | -| ~:latex-listings~ | ~org-latex-listings~ | | ~:latex-minted-langs~ | ~org-latex-minted-langs~ | | ~:latex-minted-options~ | ~org-latex-minted-options~ | | ~:latex-prefer-user-labels~ | ~org-latex-prefer-user-labels~ | | ~:latex-subtitle-format~ | ~org-latex-subtitle-format~ | | ~:latex-subtitle-separate~ | ~org-latex-subtitle-separate~ | +| ~:latex-src-block-backend~ | ~org-latex-src-block-backend~ | | ~:latex-table-scientific-notation~ | ~org-latex-table-scientific-notation~ | | ~:latex-tables-booktabs~ | ~org-latex-tables-booktabs~ | | ~:latex-tables-centered~ | ~org-latex-tables-centered~ | @@ -22256,7 +22256,7 @@ * Footnotes version 1.34 of the =htmlize.el= package, which you need to install). Fontified code chunks in LaTeX can be achieved using either the [[https://www.ctan.org/pkg/listings][listings]] package or the [[https://www.ctan.org/pkg/minted][minted]] package. Refer to -~org-latex-listings~ for details. +~org-latex-src-block-backend~ for details. [fn:115] Source code in code blocks may also be evaluated either interactively or on export. See [[*Working with Source Code]] for more diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 1e8558c7b..c5f0bcb33 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -268,6 +268,15 @@ Chmod-style permissions are based on the new variable ~org-babel-tangle-default-file-mode~. *** A new custom setting =org-agenda-clock-report-header= to add a header to org agenda clock report + +*** ~org-latex-listings~ has been replaced with ~org-latex-src-block-backend~ + +~org-latex-listings~ has been renamed to better reflect the current +purpose of the variable. The replacement variable +~org-latex-src-block-backend~ acts in exactly the same way, however it +accepts =listings= and =verbatim= in place of =t= and =nil= (which +still work, but are no longer listed as valid options). + * Version 9.5 ** Important announcements and breaking changes diff --git a/lisp/org-compat.el b/lisp/org-compat.el index f599e246e..c1a78e834 100644 --- a/lisp/org-compat.el +++ b/lisp/org-compat.el @@ -324,6 +324,8 @@ (define-obsolete-variable-alias 'org-latex-create-formula-image-program 'org-preview-latex-default-process "9.0") (define-obsolete-variable-alias 'org-latex-preview-ltxpng-directory 'org-preview-latex-image-directory "9.0") +(define-obsolete-variable-alias 'org-latex-listings + 'org-latex-src-block-backend "9.6") (define-obsolete-function-alias 'org-table-p 'org-at-table-p "9.0") (define-obsolete-function-alias 'org-on-heading-p 'org-at-heading-p "9.0") (define-obsolete-function-alias 'org-at-regexp-p 'org-in-regexp "8.3") diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el index 4d40f6a1d..3baa4e26e 100644 --- a/lisp/ox-beamer.el +++ b/lisp/ox-beamer.el @@ -858,7 +858,7 @@ (defun org-beamer-template (contents info) (and (stringp template) (format-spec template (org-latex--format-spec info)))) ;; engrave-faces-latex preamble - (when (eq org-latex-listings 'engraved) + (when (eq org-latex-src-block-backend 'engraved) (let ((src-p (org-element-map (plist-get info :parse-tree) '(src-block inline-src-block) #'identity info t)) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 9150c1011..ffa89188b 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -143,7 +143,7 @@ (org-export-define-backend 'latex (:latex-inactive-timestamp-format nil nil org-latex-inactive-timestamp-format) (:latex-inline-image-rules nil nil org-latex-inline-image-rules) (:latex-link-with-unknown-path-format nil nil org-latex-link-with-unknown-path-format) - (:latex-listings nil nil org-latex-listings) + (:latex-src-block-backend nil nil org-latex-src-block-backend) (:latex-listings-langs nil nil org-latex-listings-langs) (:latex-listings-options nil nil org-latex-listings-options) (:latex-minted-langs nil nil org-latex-minted-langs) @@ -937,22 +937,22 @@ (defcustom org-latex-format-inlinetask-function ;; Src blocks -(defcustom org-latex-listings nil - "Non-nil means export source code using the listings package. +(defcustom org-latex-src-block-backend 'verbatim + "Backend used to generate source code listings. -This package will fontify source code, possibly even with color. -There are four implementations of this functionality you may +This sets the behaviour for fontifying source code, possibly even with +color. There are four implementations of this functionality you may choose from (ordered from least to most capable): -1. Verbatim (nil) -2. Listings (t) -3. Minted (minted) -4. Engraved (engraved) +1. Verbatim +2. Listings +3. Minted +4. Engraved The first two options provide basic syntax highlighting (listings), or none at all (verbatim). -When using listings, you also need to make use of the LaTeX -\"listings\" package. The \"color\" package is also needed if you +When using listings, you also need to make use of LaTeX package +\"listings\"e. The \"color\" LaTeX package is also needed if you would like color too. These can simply be added to `org-latex-packages-alist', using customise or something like: @@ -963,27 +963,12 @@ (defcustom org-latex-listings nil There are two further options for more comprehensive fontification. The first can be set with, - (setq org-latex-listings \\='engraved) + (setq org-latex-src-block-backend \\='minted) -which causes source code to be run through -`engrave-faces-latex-buffer', which generates colorings using -Emacs' font-lock information. This requires the engrave-faces -package (availible from ELPA), and the fvextra LaTeX package be -installed. - -The styling of the engraved result can customised with -`org-latex-engraved-preamble' and `org-latex-engraved-options'. -The default preamble also uses the tcolorbox LaTeX package in -addition to fvextra. - -The second more comprehensive option can be set with, - - (setq org-latex-listings \\='minted) - -which causes source code to be exported using the minted package -as opposed to listings. If you want to use minted, you need to -add the minted package to `org-latex-packages-alist', for example -using customize, or with +which causes source code to be exported using the LaTeX package +minted as opposed to listings. If you want to use minted, you +need to add the minted package to `org-latex-packages-alist', for +example using customize, or with (require \\='ox-latex) (add-to-list \\='org-latex-packages-alist \\='(\"newfloat\" \"minted\")) @@ -996,14 +981,29 @@ (defcustom org-latex-listings nil The minted choice has possible repercussions on the preview of latex fragments (see `org-preview-latex-fragment'). If you run into previewing problems, please consult -URL `https://orgmode.org/worg/org-tutorials/org-latex-preview.html'." +URL `https://orgmode.org/worg/org-tutorials/org-latex-preview.html'. + +The most comprehensive option can be set with, + + (setq org-latex-src-block-backend \\='engraved) + +which causes source code to be run through +`engrave-faces-latex-buffer', which generates colorings using +Emacs' font-lock information. This requires the Emacs package +engrave-faces (availible from ELPA), and the LaTeX package +fvextra be installed. + +The styling of the engraved result can customised with +`org-latex-engraved-preamble' and `org-latex-engraved-options'. +The default preamble also uses the LaTeX package tcolorbox in +addition to fvextra." :group 'org-export-latex :type '(choice - (const :tag "Use listings" t) + (const :tag "Use listings" listings) (const :tag "Use minted" minted) (const :tag "Use engrave-faces-latex" engraved) - (const :tag "Export verbatim" nil)) - :safe (lambda (s) (memq s '(t nil minted engraved)))) + (const :tag "Export verbatim" verbatim)) + :safe (lambda (s) (memq s '(listings minted engraved verbatim)))) (defcustom org-latex-listings-langs '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp") @@ -1201,7 +1201,7 @@ (defcustom org-latex-engraved-preamble right=2pt, top=1pt, bottom=0.5pt, breakable}" "Preamble content injected when using engrave-faces-latex for source blocks. -This is relevant when `org-latex-listings' is set to `engraved'. +This is relevant when `org-latex-src-block-backend' is set to `engraved'. There is quite a lot of flexibility in what this preamble can be, as long as it: - Loads the fvextra package. @@ -1502,7 +1502,8 @@ (defun org-latex--caption/label-string (element info) main) (and (eq type 'src-block) (not (plist-get attr :float)) - (null (plist-get info :latex-listings))))) + (memq (plist-get info :latex-src-block-backend) + '(verbatim nil))))) (short (org-export-get-caption element t)) (caption-from-attr-latex (plist-get attr :caption))) (cond @@ -1522,7 +1523,8 @@ (defun org-latex--caption/label-string (element info) (paragraph "figure") (image "figure") (special-block "figure") - (src-block (if (plist-get info :latex-listings) + (src-block (if (not (memq (plist-get info :latex-src-block-backend) + '(verbatim nil))) "listing" "figure")) (t (symbol-name type*))) @@ -1909,7 +1911,7 @@ (defun org-latex-template (contents info) (and (stringp template) (format-spec template spec))) ;; engrave-faces-latex preamble - (when (eq org-latex-listings 'engraved) + (when (eq org-latex-src-block-backend 'engraved) (let ((src-p (org-element-map (plist-get info :parse-tree) '(src-block inline-src-block) #'identity info t)) @@ -2302,11 +2304,17 @@ (defun org-latex-inline-src-block (inline-src-block _contents info) contextual information." (let ((code (org-element-property :value inline-src-block)) (lang (org-element-property :language inline-src-block))) - (pcase (plist-get info :latex-listings) - ('nil (org-latex--text-markup code 'code info)) + (pcase (plist-get info :latex-src-block-backend) + ('verbatim (org-latex--text-markup code 'code info)) ('minted (org-latex-inline-src-block--minted info code lang)) ('engraved (org-latex-inline-src-block--engraved info code lang)) - (_ (org-latex-inline-src-block--listings info code lang))))) + ('listings (org-latex-inline-src-block--listings info code lang)) + (oldval + (message "Please update the LaTeX src-block-backend to %s" + (if oldval "listings" "verbatim")) + (if oldval + (org-latex-inline-src-block--listings info code lang) + (org-latex--text-markup code 'code info)))))) (defun org-latex-inline-src-block--minted (info code lang) "Transcode an inline src block's content from Org to LaTeX, using minted. @@ -2489,7 +2497,7 @@ (defun org-latex-keyword (keyword _contents info) (concat depth (and depth "\n") "\\tableofcontents")))) ((string-match-p "\\" value) "\\listoftables") ((string-match-p "\\" value) - (cl-case (plist-get info :latex-listings) + (cl-case (plist-get info :latex-src-block-backend) ((nil) "\\listoffigures") (minted "\\listoflistings") (otherwise "\\lstlistoflistings"))))))))) @@ -3175,15 +3183,20 @@ (defun org-latex-src-block (src-block _contents info) (num-start (org-export-get-loc src-block info)) (retain-labels (org-element-property :retain-labels src-block)) (attributes (org-export-read-attribute :attr_latex src-block)) - (float (plist-get attributes :float)) - (listings (plist-get info :latex-listings))) + (float (plist-get attributes :float))) (funcall - (pcase listings - ((or (pred not) (guard (not lang))) #'org-latex-src-block--verbatim) - ((guard custom-env) #'org-latex-src-block--custom) + (pcase (plist-get info :latex-src-block-backend) + ((or 'verbatim (guard (not lang))) #'org-latex-src-block--verbatim) ('minted #'org-latex-src-block--minted) ('engraved #'org-latex-src-block--engraved) - (_ #'org-latex-src-block--listings)) + ('listings #'org-latex-src-block--listings) + ((guard custom-env) #'org-latex-src-block--custom) + (oldval + (message "Please update the LaTeX src-block-backend to %s" + (if oldval "listings" "verbatim")) + (if oldval + #'org-latex-src-block--listings + #'org-latex-src-block--verbatim))) :src-block src-block :info info :lang lang diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 25e02b258..28f950813 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -3978,7 +3978,7 @@ (ert-deftest test-org-export/latex-src-block-verbatim-caption () \\end{verbatim} \\caption{Caption is below, 60\\%s} \\end{figure*}" - (let ((org-latex-listings 'minted) ; inactive due to missing lang + (let ((org-latex-src-block-backend 'minted) ; inactive due to missing lang (org-latex-default-figure-position "tp")) ;; Namely "multicolumn" value to get just figure environment ;; looks like a bug. -- 2.35.3 --=-=-=--