I am attaching a patch in case anyone wants to try this proposal. A
function for ox-latex is included.
Syntax:
&[optional parameters]{contents}
With this patch, something like &foo{lorem ipsum dolor} is exported to
LaTeX as \foo{lorem ipsum dolor}.
Blocks can be nested, e.g.: &foo{lorem ipsum &bar{dolor}}.
Regarding the "optional parameters", there is nothing defined, although
I think they should be adapted to each backend. A possible use that
occurs to me:
&foo[prelatex: [lorem] postlatex: {ipsum} html: style="color:red;"]{blah blah}
This should produce in LaTeX:
\foo[lorem]{blah blah}{ipsum}
and in HTML:
<span class="foo" style="color:red;">blah blah</span>
Best regards,
Juan Manuel
--
Juan Manuel Macías -- Composición tipográfica, tratamiento de datos, diseño
editorial y ortotipografía
>From 587e77feb1c4e6881d527d1fd3a6e541efb596d4 Mon Sep 17 00:00:00 2001
From: Juan Manuel Macias <[email protected]>
Date: Wed, 21 Feb 2024 20:44:58 +0100
Subject: [PATCH] org-element.el: New element: Inline Special Block (proof of
concept).
* lisp/ox-latex.el (org-latex-inline-special-block): A possible
function for the LaTeX backend.
---
lisp/org-element.el | 55 ++++++++++++++++++++++++++++++++++++++++++++-
lisp/ox-latex.el | 10 +++++++++
2 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 6691ea44e..2f9436df2 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -272,6 +272,8 @@ specially in `org-element--object-lex'.")
"\\|"))
;; Objects starting with "@": export snippets.
"@@"
+ ;; Objects starting with "&": inline-special-blocks.
+ "&"
;; Objects starting with "{": macro.
"{{{"
;; Objects starting with "<" : timestamp
@@ -313,7 +315,7 @@ specially in `org-element--object-lex'.")
"List of recursive element types aka Greater Elements.")
(defconst org-element-all-objects
- '(bold citation citation-reference code entity export-snippet
+ '(bold citation citation-reference code entity export-snippet inline-special-block
footnote-reference inline-babel-call inline-src-block italic line-break
latex-fragment link macro radio-target statistics-cookie strike-through
subscript superscript table-cell target timestamp underline verbatim)
@@ -440,6 +442,7 @@ Don't modify it, set `org-element-affiliated-keywords' instead.")
;; Ignore inline babel call and inline source block as formulas
;; are possible. Also ignore line breaks and statistics
;; cookies.
+ (inline-special-block ,@standard-set)
(table-cell citation export-snippet footnote-reference link macro
radio-target target timestamp ,@minimal-set)
(table-row table-cell)
@@ -3535,6 +3538,54 @@ Assume point is at the beginning of the entity."
(org-element-property :name entity)
(when (org-element-property :use-brackets-p entity) "{}")))
+;;;; inline special block
+
+(defun org-element-inline-special-block-parser ()
+ "Parse inline special block at point.
+
+When at an inline special block, return a new syntax node of
+`inline-special-block' type containing `:begin', `:end', `:type',
+`:parameters', `:contents-begin', `:contents-end' and
+`:post-blank' as properties. Otherwise, return nil.
+
+Assume point is at the beginning of the block."
+ (save-excursion
+ (when (looking-at "&\\([A-Za-z]+\\)[{[]")
+ (goto-char (- (match-end 0) 1))
+ (let* ((begin (match-beginning 0))
+ (parameters
+ (let ((p (org-element--parse-paired-brackets ?\[)))
+ (and (org-string-nw-p p)
+ (replace-regexp-in-string "\n[ \t]*" " " (org-trim p)))))
+ (contents-begin (when (looking-at-p "{") (+ (point) 1)))
+ (type (org-element--get-cached-string
+ (match-string-no-properties 1)))
+ (contents-end
+ (progn
+ (goto-char (- contents-begin 1))
+ (org-element--parse-paired-brackets ?\{)
+ (- (point) 1)))
+ (post-blank (skip-chars-forward " \t"))
+ (end (point)))
+ (when contents-end
+ (org-element-create
+ 'inline-special-block
+ (list :type type
+ :parameters parameters
+ :contents-begin contents-begin
+ :contents-end contents-end
+ :begin begin
+ :end end
+ :post-blank post-blank)))))))
+
+(defun org-element-inline-special-block-interpreter (inline-special-block contents)
+ "Interpret INLINE SPECIAL BLOCK object as Org syntax."
+ (let ((type (org-element-property :type inline-special-block))
+ (opts (org-element-property :parameters inline-special-block)))
+ (format "&%s%s{%s}"
+ type
+ (if opts (format "[%s]" opts) "")
+ contents)))
;;;; Export Snippet
@@ -5260,6 +5311,8 @@ to an appropriate container (e.g., a paragraph)."
(org-element-strike-through-parser)))
(?@ (and (memq 'export-snippet restriction)
(org-element-export-snippet-parser)))
+ (?& (and (memq 'inline-special-block restriction)
+ (org-element-inline-special-block-parser)))
(?{ (and (memq 'macro restriction)
(org-element-macro-parser)))
(?$ (and (memq 'latex-fragment restriction)
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index cfa2b8178..a303d54a6 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -101,6 +101,7 @@
(underline . org-latex-underline)
(verbatim . org-latex-verbatim)
(verse-block . org-latex-verse-block)
+ (inline-special-block . org-latex-inline-special-block)
;; Pseudo objects and elements.
(latex-math-block . org-latex-math-block)
(latex-matrices . org-latex-matrices))
@@ -2095,6 +2096,15 @@ holding contextual information."
center-block (format "\\begin{center}\n%s\\end{center}" contents) info))
+;;;; Inline Special Block
+
+(defun org-latex-inline-special-block (inline-special-block contents info)
+ "Transcode an INLINE SPECIAL BLOCK element from Org to LaTeX.
+CONTENTS holds the contents of the block. INFO is a plist
+holding contextual information."
+ (let ((type (org-element-property :type inline-special-block)))
+ (format "\\%s{%s}" type contents)))
+
;;;; Clock
(defun org-latex-clock (clock _contents info)
--
2.43.1