From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id WBBQLo6xcmIPHAAAbAwnHQ (envelope-from ) for ; Wed, 04 May 2022 19:02:06 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id 6zBbLo6xcmJVKQAAauVa8A (envelope-from ) for ; Wed, 04 May 2022 19:02:06 +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 89429325D9 for ; Wed, 4 May 2022 19:00:56 +0200 (CEST) Received: from localhost ([::1]:58754 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nmI6g-0001R6-AY for larch@yhetil.org; Wed, 04 May 2022 12:44:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53856) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nmI42-0007KS-GD for emacs-orgmode@gnu.org; Wed, 04 May 2022 12:41:23 -0400 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]:39530) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nmI3y-0007hQ-6a for emacs-orgmode@gnu.org; Wed, 04 May 2022 12:41:22 -0400 Received: by mail-pg1-x533.google.com with SMTP id i62so1589309pgd.6 for ; Wed, 04 May 2022 09:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:user-agent:message-id:mime-version; bh=bTW2rWv6rgjGZL4lJ0/rpIqaPwKutXkZ4f1F0+jffAg=; b=GS0+QVeH6ozE28CcIwDQKvgzoD4swVRpIz1O7AovLR+RtY1wb+cPFnbAFerqygrbxT sU0SzMNQtVhn3fuViShhVlC5I0jD8K+SMvWVYF7gjeGB6Di0B2TC7VDXnP3pPynFUg2V d8EaDsdnDz+LuQnzqnxU9K5A9f0RH9bLxMsk8ILgTosX1um5kMxijyCC6XXywzENqQrh hJXnO7V5/fhRvvO5z40tZeLaD0EN7i47D2E6laRR/XHGkDcBk4gY1m3p8eJobY2IRrzr DAGuN6GgzV+pbONP+0ilbzphiCkpFxJFpTA9PuhLKjBqM7FXdBk3CBsFH+EjmHXlRm8a N4bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:user-agent:message-id :mime-version; bh=bTW2rWv6rgjGZL4lJ0/rpIqaPwKutXkZ4f1F0+jffAg=; b=rf93meiFdrhICOsZw5quNjd2iXvSN320jcPzdayA3PnNMTypzLv/fUeTMNA7yd4NX8 FjjgqUrC+8TVQx0W1FzR40p66wCsiAd0VgJn+Uddl0/PGbzS7+Jpm4GlBltVvVrsWCB/ loDQUtv02wAiA4FlIIV7SuOt9vFmpsAj09tdiHQ2RRlwFFx5MTUF8UK1dowjoBZMhCyE TidwYK3CjjM20+kLIGp+ouP/vCO/G7dDgxZRmNdsNelZYbC37WPkP6ZhjB2ILUfoPLeW VECnLGCVZGp6awl3rq8yd4U6zj2I7fpNIADsOrLz6wEe0ZtkKNKwMKvfPeKdSYxTQEMp 3dbA== X-Gm-Message-State: AOAM531yyZPOzxE2v4vF52pzYMn6N7GH5dVLks+mFuciTacPyR5HZ8RP aRciS9rWrGFleJH8LIsrriZVZPnOWr4= X-Google-Smtp-Source: ABdhPJwOW5ROg4rj+lbjiwDHDYdND4dumxK7MLjf9GWs/gs+CbJqOGNTRuwRWXKiQNAPxr8zoIU3Ig== X-Received: by 2002:a65:6498:0:b0:3c5:fc22:abbc with SMTP id e24-20020a656498000000b003c5fc22abbcmr1588354pgv.64.1651682475860; Wed, 04 May 2022 09:41:15 -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 f12-20020aa78b0c000000b0050dc76281f9sm8436763pfd.211.2022.05.04.09.41.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 May 2022 09:41:15 -0700 (PDT) From: Timothy To: emacs-orgmode@gnu.org, Daniel Fleischer , Nicolas Goaziou Subject: [PATCH] New LaTeX code export option: engraved Date: Wed, 04 May 2022 23:59:02 +0800 User-agent: mu4e 1.6.10; emacs 28.0.92 Message-ID: <87wnf1z1w8.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2607:f8b0:4864:20::533; envelope-from=tecosaur@gmail.com; helo=mail-pg1-x533.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, HTML_MESSAGE=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=1651683656; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=X69PivmldOYfqWFlnSqJGCGKRhLRubwoK/7qhUMlKII=; b=Pvcajfjn+GmHPWaWr8WBWLEHaNHnTVz1uqM+C+4g0HJpGI3zLCbCfFRfkyg4zDM9P/lk1g /ewl8jSCDM6hd8Nm05yCcDbvb3aTVx5DxvlBHx0JieAZ/LLG/YXM8EvxtlGzTltV0Y5Fcm sse7nlqGaaIjl4XnKVPKQ4njFb6DOfi2J01bSYrRg3Lq9e/AiULbpdIDysSLsYGfOj0vce fQTo/JTkTlp+8atuc2pqJEL9LC1JaQEHJpj94NyYfk4eppvTK5oUpcwGUFxUTtsIYGMPvJ G3L4x1QZRoB1i4ec5/6AeshjxtWZvbmiLb4jeBCYQJDSlt2KwhF9yAbOajU7Hg== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1651683656; a=rsa-sha256; cv=none; b=L5nBLWKUlQZONVGEhtO0pnR2nPSKH45C/fdZIrMcnhJYA/thhBw6OVwG4zShPSprmdnt/R dLg4F21oOCntkTaJI0Gr7LKPzy6fgx5cH9lrAnA1dJOFIyBMM4OqHdv4poYf/9u4sDTMuG ZQ8sDEwDMva87lbRlHOxl90J85adb6KrckqF5FOEtVtq/77cja13f7vlaPLYsdPplk46U/ uwtAbwR1yUyIh4KrIx+0C0BB3D0MkrJYRHrclZBkH0WyR3SZHR6sLKux7vU8tgY1zIaMkh MwAiIRIFA1Lqs6Dz4XthAnbvnSeuRWcdGQjXVCKOhV/fqWYaAyvaZu0FmcvTyg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20210112 header.b=GS0+QVeH; 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.22 Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20210112 header.b=GS0+QVeH; 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: 89429325D9 X-Spam-Score: 6.22 X-Migadu-Scanner: scn0.migadu.com X-TUID: auB1eDogde6J --=-=-= Content-Type: multipart/alternative; boundary="==-=-=" --==-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi All, I=E2=80=99ve been fairly busy as of late (hence my recent silence on this M= L), however I have a patchset that=E2=80=99s been in the works for a while that I=E2=80= =99ve finally polished up. Short version: It adds a new (superior) option for exporting code blocks wi= th syntax highlighting to LaTeX. The long version follows. Currently there are four options for exporting code to LaTeX (ordered by complexity/quality). 1. Verbatim, which simply includes the code unstyled 2. Custom, which puts the code in an enviroment of your choice 3. Listings, which uses the LaTeX package by this name. This is quick, but exceedingly basic. 4. Minted, which uses the LaTeX package by this name. This is slow, but pro= duces better results than Listings This patchset accomplishes two things: 1. It refactors the overly large `org-latex-src-block' function, and makes = a few other improvements to pre-existing code 2. It adds a new option for exporting code, named (you guessed it!) =E2=80= =9Cengraved=E2=80=9D What is this new option, and why do we want it? About a year ago I started work on a package that generalises the functiona= lity of `htmlize.el', termed `engrave-faces' (). It provides the abili= ty to extract font-lock information and export it to a number of formats: html, a= nsi, and (crucially) LaTeX! Since the LaTeX export is built on the `fvextra' (La= TeX) package (like pygments), the vast majority of the Minted options you=E2=80= =99re used to just carry over. This allows for a result that is, I think, straight up better than all the pre-existing options. For starters, you can now apply syntax highlighting t= o any language you have a major mode for. There are a number of optimisations unattempted, but it already significant= ly outperforms Minted. Here are some timings from my `config.org': =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94= =81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81= =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94= =81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81= =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81 LaTeX code backend Compile time Overhead Overhead ratio=20 =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80 verbatim 12 s 0 0.0=20 lstlistings 15 s 3 s 0.2=20 Engrave 34 s 22 s 1.8=20 Pygments (Minted) 184 s 172 s 14.3=20 =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94= =81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81= =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94= =81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81= =E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2=94=81=E2= =94=81=E2=94=81 Compared to Minted, we also no longer have to install `pygments' or pass the `--shelll-escape' flag to LaTeX to generate passable code blocks. Having an all-emacs system also allows for some nifty things, like having e= ntire documents/presentations based on your Emacs theme (see ). Demo images: , . Here are some more screenshots to see what the result can look like in prac= tice: =E2=80=A2 =E2=80=A2 =E2=80=A2 So, please take a look at the patches, give this a whirl, and let me know w= hat you think! =F0=9F=98=80 All the best, Timothy --==-=-= Content-Type: text/html; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable =

Hi All,

I=E2=80=99ve been fairly busy as of late (hence my recent silence on this <= span class=3D"acr">ML), however I have a patchset that=E2=80=99s been in the works for a while that I=E2=80= =99ve finally polished up.

Short version: It adds a new (superior) option for exporting code blocks wi= th syntax highlighting to LaTeX.

The long version follows.

Currently there are four options for exporting code to LaTeX (ordered by complexity/quality).

  1. Verbatim, which simply i= ncludes the code unstyled
  2. Custom, which puts the code in an enviroment of your choice
  3. Listings, which uses the LaTeX package by this name. This is quick, but exceedingly basic.
  4. Minted, which uses the LaTeX package by this name. This is slow, but pr= oduces better results than Listings

This patchset accomplishes two things:

  1. It refactors the overly = large org-latex-src-block function, and makes a f= ew other improvements to pre-existing code
  2. It adds a new option for exporting code, named (you guessed it!) =E2=80= =9Cengraved=E2=80=9D

What is this new option, and why do we want it?

About a year ago I started work on a package that generalises the functiona= lity of htmlize.el, termed engrave-faces (https://elpa.gnu.org/packages/engrave-faces.html). It provi= des the ability to extract font-lock information and export it to a number of formats: html, a= nsi, and (crucially) LaTeX! Since the LaTeX export is built on the fvextra (LaTeX) package (like pygments), the vast majority of the Minted options you=E2=80= =99re used to just carry over.

This allows for a result that is, I think, straight up better than all the pre-existing options. For starters, you can now apply syntax highlighting t= o any language you have a major mode for.

There are a number of optimisations unattempted, but it already significant= ly outperforms Minted. Here are some timings from my config.org:

<= /colgroup>
LaTeX code backend Compile time Overhead Overhead ratio
verbatim 12 s 0 0.0
ls= tlistings 15 s 3 s 0.2
En= grave 34 s 22 s 1.8
Py= gments (Minted) 184 s 172 s 14.3

Compared to Minted, we also no longer have to install pygments or pass the --shelll-escape flag to LaTeX to = generate passable code blocks.

Having an all-emacs system also allows for some nifty things, like having e= ntire documents/presentations based on your Emacs theme (see https://github.com/tecosaur/ox-chameleon). Demo images: 3D"oAl1.png"/, 3D"oAle.png"/.

Here are some more screenshots to see what the result can look like in prac= tice:

  • 3D"oAl2.png"/
  • 3D"oAl_.png"/
  • 3D"oAlL.png"/

So, please take a look at the patches, give this a whirl, and let me know w= hat you think! =F0=9F=98=80

All the best,
Timothy

--==-=-=-- --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-ox-latex-Refactor-org-latex-src-block.patch >From 87872cc8f2fb1da1a03dc4aadfbd4af6541d8c13 Mon Sep 17 00:00:00 2001 From: TEC Date: Sun, 21 Nov 2021 14:35:34 +0800 Subject: [PATCH 1/4] 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..63855d2f6 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 a4d833418c3e2f0a8f365b92c01c091f75b6482d Mon Sep 17 00:00:00 2001 From: TEC Date: Wed, 4 May 2022 18:53:10 +0800 Subject: [PATCH 2/4] 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 | 58 +++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 63855d2f6..ed66a51c0 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -2127,36 +2127,34 @@ (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) + (let ((mint-lang (or (cadr (assq (intern 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))) + +(defun org-latex-inline-src-block--listings (info code lang) + (let* ((lst-lang (or (cadr (assq (intern lang) + (plist-get info :latex-listings-langs))) + org-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 b322e67cc8b88826be26ee8ae155467aa764e743 Mon Sep 17 00:00:00 2001 From: TEC Date: Wed, 4 May 2022 23:31:59 +0800 Subject: [PATCH 3/4] 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 ed66a51c0..6a29efcba 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 e0310e21e260a930e06d704ec8893ab1e75518aa Mon Sep 17 00:00:00 2001 From: TEC Date: Sun, 21 Nov 2021 20:04:12 +0800 Subject: [PATCH 4/4] 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-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. --- lisp/ox-beamer.el | 9 ++ lisp/ox-latex.el | 235 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 241 insertions(+), 3 deletions(-) diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el index 6be73c91e..ca1aeafe4 100644 --- a/lisp/ox-beamer.el +++ b/lisp/ox-beamer.el @@ -857,6 +857,15 @@ (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 + (let ((engraved-p (eq org-latex-listings 'engraved)) + (src-p (org-element-map (plist-get info :parse-tree) + '(src-block inline-src-block) #'identity)) + (fixedw-p + (org-element-map (plist-get info :parse-tree) + '(example-block fixed-width) #'identity))) + (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 6a29efcba..4cc82f6e7 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) @@ -946,7 +950,24 @@ (defcustom org-latex-listings nil (add-to-list \\='org-latex-packages-alist \\='(\"\" \"listings\")) (add-to-list \\='org-latex-packages-alist \\='(\"\" \"color\")) -Alternatively, +There are two fancier options for fontification. + +The first fancy alternative, + + (setq org-latex-listings \\='engraved) + +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 fancy alternative, (setq org-latex-listings \\='minted) @@ -971,8 +992,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 +1164,109 @@ (defcustom org-latex-custom-lang-environments nil :version "26.1" :package-version '(Org . "9.0")) +(defcustom org-latex-engraved-preamble + "\\usepackage{fvextra} + +[FVEXTRA-SETUP] + +\\renewcommand\\theFancyVerbLine{\\footnotesize\\color{black!40!white}\\arabic{FancyVerbLine}} + +\\providecolor{codebackground}{HTML}{f7f7f7} +\\providecolor{codeborder}{HTML}{f0f0f0} +\\providecolor{EFD}{HTML}{28292e} + +% TODO have code boxes keep line vertical alignment +\\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. +- Defines a \"Code\" environment (note the capital C), which can be + later used to wrap \"Verbatim\" environments (provided by fvextra). + +A macro-like placeholder is used to set fvextra's defaults according to +`org-latex-engraved-options': + + [FVEXTRA-SETUP]" + :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 + \\='((\"bgcolor\" \"bg\") (\"frame\" \"lines\"))) + ; or + (setq org-latex-engraved-options + \\='((\"bgcolor\" . \"bg\") (\"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") + +(defun org-latex-generate-engraved-preamble (info syntax-colours-p) + (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?" + org-latex-engraved-preamble) + (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 +1881,15 @@ (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 + (let ((engraved-p (eq org-latex-listings 'engraved)) + (src-p (org-element-map (plist-get info :parse-tree) + '(src-block inline-src-block) #'identity)) + (fixedw-p + (org-element-map (plist-get info :parse-tree) + '(example-block fixed-width) #'identity))) + (when (or src-p fixedw-p) + (org-latex-generate-engraved-preamble info src-p))) ;; Document start. "\\begin{document}\n\n" ;; Title command. @@ -2142,12 +2276,13 @@ (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) (let ((mint-lang (or (cadr (assq (intern lang) (plist-get info :latex-minted-langs))) - (downcase org-lang))) + (downcase lang))) (options (org-latex--make-option-string (plist-get info :latex-minted-options)))) (format "\\mintinline%s{%s}{%s}" @@ -2155,6 +2290,23 @@ (defun org-latex-inline-src-block--minted (info code lang) mint-lang code))) +(defun org-latex-inline-src-block--engraved (info code lang) + (if (require 'engrave-faces-latex nil t) + (let (engraved-buffer engraved-code) + (setq engraved-buffer + (with-temp-buffer + (insert code) + (funcall (org-src-get-lang-mode lang)) + (engrave-faces-latex-buffer))) + (setq engraved-code + (with-current-buffer engraved-buffer + (buffer-string))) + (kill-buffer engraved-buffer) + (format "\\Verb{%s}" + engraved-code)) + (message "Cannot engrave inline src block, `engrave-faces-latex' is unavailible.") + (insert (org-latex--text-markup code 'code info)))) + (defun org-latex-inline-src-block--listings (info code lang) (let* ((lst-lang (or (cadr (assq (intern lang) (plist-get info :latex-listings-langs))) @@ -3013,6 +3165,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 @@ -3129,6 +3284,80 @@ (defun org-latex-src-block--minted ;; Return value. (format float-env body))) +(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'." + (if (require 'engrave-faces-latex nil t) + (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-buffer + (with-temp-buffer + (insert + (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))))) + (funcall (org-src-get-lang-mode lang)) + (engrave-faces-latex-buffer))) + (content + (with-current-buffer content-buffer + (buffer-string))) + (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)))))) + content))) + (kill-buffer content-buffer) + ;; Return value. + (format float-env body)) + (message "Cannot engrave src block, `engrave-faces-latex' is unavailible.") + (insert (org-latex--text-markup code 'code info)))) + (defun org-latex-src-block--listings (src-block info lang caption caption-above-p label num-start retain-labels attributes float) -- 2.35.3 --=-=-=--