From: Timothy <tecosaur@gmail.com>
To: Ihor Radchenko <yantar92@gmail.com>
Cc: emacs-orgmode@gnu.org, Daniel Fleischer <danflscr@gmail.com>,
Nicolas Goaziou <mail@nicolasgoaziou.fr>
Subject: Re: [PATCH] New LaTeX code export option: engraved
Date: Thu, 05 May 2022 23:17:44 +0800 [thread overview]
Message-ID: <87v8ukyo94.fsf@gmail.com> (raw)
In-Reply-To: <87sfpogyag.fsf@localhost>
[-- Attachment #1: Type: text/plain, Size: 2879 bytes --]
Hi Ihor,
> Thanks!
> Implementing fontification using Emacs capabilities is certainly a step
> in the right direction. LaTeX support for fontification has always been
> tricky.
I’m glad to hear you’re of a similar mind to me with this.
> - I tried to test your patch, and it only works partially. There is some
> stray text caused by LaTeX errors:
>
> [2. application/vnd.lotus-organizer; test.org]…
> [3. application/pdf; test.pdf]…
Ah. I thought that hyperref loaded xcolor, but it seems my assumption was
incorrect. I’ve added `\usepackage{xcolor}' to the default
`org-latex-engraved-preamble', but maybe I should ask people to modify
`org-latex-packages-alist'. I’m not sure.
> - You did not add a NEWS entry and did not update the manual in your patch.
I’m waiting till the functional content of these packages is settled/accepted,
and then I’ll write NEWS and manual entries.
> - There are many compiler warnings emitted when compiling Org with your patch
Oops, I keep on forgetting to check byte compilation. These should all be fixed now.
> The docstrings are missing in the above.
Docstrings have been added.
> I am not sure why, but the word fancy feels slightly annoying here.
Docsting rewritten.
> Since engraved is not entirely relying on LaTeX options, a lot of
> customisation is not mentioned in this docstring. AFAIU, color
> customisation is only possible by changing defcustoms from engrave-faces
> package.
>
> Another related note is what is going to happen in beamer export with
> dark background. The default face mapping in engrave-faces is using some
> kind of light theme, which may lose all the contrast on not-light
> background.
Modifying the style of engraved-faces-latex’s output is indeed done by
customising a engraved-faces variable. I don’t think we should attempt to do
anything further with this within Org.
To elaborate a bit, the generated LaTeX uses the styling information given in
`engrave-faces-preset-styles'. Changing this to use the current Emacs theme is as
simple as `(setq engrave-faces-preset-styles (engrave-faces-generate-preset))'.
> It feels that codebackground, codeborder, and EFD should be customizable
> by org-latex-engraved-options.
Hmm. I don’t think so. They are entirely self-contained within the preamble
variable. Should there be a nice existing `org-latex-user-colors' variable or
such, it would make a lot of sense to shove this there, but since no such
variable exists I’m not sure we can really do much better than just asking users
to modify `org-latex-engraved-preamble'.
> Docstring?
Added.
>> + (message “Cannot engrave inline src block, `engrave-faces-latex’ is unavailible.”)
>
> Why message instead of error?
User errors are now thrown.
Thanks for the feedback!
Timothy
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox-latex-Refactor-org-latex-src-block.patch --]
[-- Type: text/x-patch, Size: 15942 bytes --]
From d231437e2c9f96bf70520d9ddda810a95667fcdd Mon Sep 17 00:00:00 2001
From: TEC <tec@tecosaur.com>
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..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
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-ox-latex-Refactor-org-latex-inline-src-block.patch --]
[-- Type: text/x-patch, Size: 4020 bytes --]
From ea5d116b06326be46e3053e6ded26d5b8b0638d9 Mon Sep 17 00:00:00 2001
From: TEC <tec@tecosaur.com>
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 | 62 +++++++++++++++++++++++++-----------------------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index c2f728a1c..2b732cf16 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 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)
+ "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
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-ox-latex-More-versitile-option-construction.patch --]
[-- Type: text/x-patch, Size: 4116 bytes --]
From aa0a9dafab7a7246e2855a2257d4c156eb48752c Mon Sep 17 00:00:00 2001
From: TEC <tec@tecosaur.com>
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 2b732cf16..4181db175 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
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: 0004-ox-latex-Introduce-engraved-code-highlighting.patch --]
[-- Type: text/x-patch, Size: 17464 bytes --]
From 90849f3986cc709c1d01ec9f204a7eb8b940cd27 Mon Sep 17 00:00:00 2001
From: TEC <tec@tecosaur.com>
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 | 273 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 272 insertions(+), 10 deletions(-)
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index 6be73c91e..73bd95539 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
+ (when (eq org-latex-listings 'engraved)
+ (let ((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 4181db175..831509a26 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")
\f
;;; 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 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 used 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,124 @@ (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}}
+
+\\usepackage{xcolor}
+
+\\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.
+- Loads the package xcolor (if it is not already loader elsewhere).
+- 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]
+
+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 <LANG>
+ ...
+ #+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 `org-latex-engraved-preamble' and
+`org-latex-engraved-options'."
+ (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)
+ (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 +1905,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
+ (when (eq org-latex-listings 'engraved)
+ (let ((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,6 +2300,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)
@@ -2149,7 +2308,7 @@ (defun org-latex-inline-src-block--minted (info code lang)
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 org-lang)))
+ (downcase lang)))
(options (org-latex--make-option-string
(plist-get info :latex-minted-options))))
(format "\\mintinline%s{%s}{%s}"
@@ -2157,6 +2316,24 @@ (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'."
+ (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))
+ (user-error "Cannot engrave inline src block, `engrave-faces-latex' is unavailible.")))
+
(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 +3194,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 +3313,79 @@ (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))
+ (user-error "Cannot engrave src block, `engrave-faces-latex' is unavailible.")))
+
(defun org-latex-src-block--listings
(src-block info lang caption caption-above-p label
num-start retain-labels attributes float)
--
2.35.3
next prev parent reply other threads:[~2022-05-05 15:50 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-04 15:59 [PATCH] New LaTeX code export option: engraved Timothy
2022-05-05 7:52 ` Daniel Fleischer
2022-05-05 16:09 ` Timothy
2022-05-06 2:35 ` Ihor Radchenko
2022-05-06 11:23 ` Timothy
2022-05-05 7:54 ` Daniel Fleischer
2022-05-05 8:48 ` Ihor Radchenko
2022-05-05 15:17 ` Timothy [this message]
2022-05-05 16:13 ` Timothy
2022-05-07 5:16 ` Ihor Radchenko
2022-05-07 6:57 ` Timothy
2022-05-07 10:40 ` Timothy
2022-05-07 11:33 ` Daniel Fleischer
2022-05-08 14:30 ` [PATCH] (v2) " Timothy
2022-05-09 6:20 ` Ihor Radchenko
2022-05-09 12:57 ` Timothy
2022-05-10 8:00 ` Max Nikulin
2022-05-11 11:06 ` Ihor Radchenko
2022-05-11 16:05 ` [PATCH] (v3) " Timothy
2022-05-12 16:40 ` Daniel Fleischer
2022-05-12 16:44 ` Timothy
2022-05-05 16:48 ` [PATCH] " Max Nikulin
2022-05-07 4:13 ` Ihor Radchenko
2022-05-09 19:19 ` Sébastien Miquel
2022-05-10 1:13 ` Timothy
2022-05-10 16:10 ` Timothy
2022-05-10 17:53 ` Sébastien Miquel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87v8ukyo94.fsf@gmail.com \
--to=tecosaur@gmail.com \
--cc=danflscr@gmail.com \
--cc=emacs-orgmode@gnu.org \
--cc=mail@nicolasgoaziou.fr \
--cc=yantar92@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).