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 <maciasch...@posteo.net>
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

Reply via email to