* Re: texinfo export has no targets for src blocks
2024-12-14 14:22 texinfo export has no targets for src blocks Fraga, Eric
@ 2024-12-23 15:10 ` Ihor Radchenko
2024-12-23 15:25 ` Fraga, Eric
0 siblings, 1 reply; 4+ messages in thread
From: Ihor Radchenko @ 2024-12-23 15:10 UTC (permalink / raw)
To: Fraga, Eric; +Cc: Emacs Org mode mailing list
[-- Attachment #1: Type: text/plain, Size: 825 bytes --]
"Fraga, Eric" <e.fraga@ucl.ac.uk> writes:
> but also happen to have a code block
>
> #+name: model
> #+begin_src ...
>
> exporting to texinfo, asking to refer to [[model]], creates a reference
> to an non-existing target ("model") because (a) org appears to assume
> that you wish to reference the src block, not the headline, and (b) the
> src block (/@example/ in texinfo) is not labelled in the .texi output.
> See attached minimal example.
> ...
Thanks for reporting!
I tried to add support for #+name'd elements in ox-texinfo.
See the attached patch.
I simply prepended an @anchor to all paragraph level Org markup
elements. However, I am not 100% sure if it is always safe to do.
May you please test the patch on your side to make sure that things are
not going to be broken? (they are not on Org manual, at least)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox-texinfo-Support-references-to-name-d-elements.patch --]
[-- Type: text/x-patch, Size: 12835 bytes --]
From 3055cf517ba665f00820a179299df4cb43333c9b Mon Sep 17 00:00:00 2001
Message-ID: <3055cf517ba665f00820a179299df4cb43333c9b.1734966481.git.yantar92@posteo.net>
From: Ihor Radchenko <yantar92@posteo.net>
Date: Mon, 23 Dec 2024 16:06:07 +0100
Subject: [PATCH] ox-texinfo: Support references to #+name'd elements
* lisp/ox-texinfo.el (org-texinfo--prepend-anchor-maybe): New helper
function prepending an archor to named text.
(org-texinfo-center-block):
(org-texinfo-drawer):
(org-texinfo-dynamic-block):
(org-texinfo-example-block):
(org-texinfo-fixed-width):
(org-texinfo-latex-environment):
(org-texinfo-paragraph):
(org-texinfo-plain-list):
(org-texinfo-quote-block):
(org-texinfo-special-block):
(org-texinfo-src-block):
(org-texinfo-table):
(org-texinfo-verse-block): Use the new helper.
* testing/lisp/test-ox-texinfo.el (test-ox-texinfo/anchors): New test.
Reported-by: Fraga, Eric <e.fraga@ucl.ac.uk>
Link: https://orgmode.org/list/87h676qr8n.fsf@ucl.ac.uk
---
lisp/ox-texinfo.el | 124 ++++++++++++++++++++------------
testing/lisp/test-ox-texinfo.el | 50 +++++++++++++
2 files changed, 128 insertions(+), 46 deletions(-)
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index cf7a96f78d..9e96d6c94f 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -553,6 +553,14 @@ (defun org-texinfo--get-node (datum info)
(plist-put info :texinfo-node-cache (cons (cons datum name) cache))
name))))
+(defun org-texinfo--prepend-anchor-maybe (contents node)
+ "Maybe prepend NODE anchor before CONTENTS.
+When NODE has :name property, prepend anchor named as :name value to
+CONTENTS. Otherwise, return CONTENTS."
+ (if-let* ((label (org-element-property :name node)))
+ (concat "@anchor{" label "}\n" contents)
+ contents))
+
(defun org-texinfo--sanitize-node (title)
"Bend string TITLE to node line requirements.
Trim string and collapse multiple whitespace characters as they
@@ -930,11 +938,13 @@ (defun org-texinfo-bold (_bold contents info)
;;;; Center Block
-(defun org-texinfo-center-block (_center-block contents _info)
+(defun org-texinfo-center-block (center-block contents _info)
"Transcode a CENTER-BLOCK element from Org to Texinfo.
CONTENTS holds the contents of the block. INFO is a plist used
as a communication channel."
- (replace-regexp-in-string "\\(^\\).*?\\S-" "@center " contents nil nil 1))
+ (org-texinfo--prepend-anchor-maybe
+ (replace-regexp-in-string "\\(^\\).*?\\S-" "@center " contents nil nil 1)
+ center-block))
;;;; Clock
@@ -968,15 +978,15 @@ (defun org-texinfo-drawer (drawer contents info)
(let* ((name (org-element-property :drawer-name drawer))
(output (funcall (plist-get info :texinfo-format-drawer-function)
name contents)))
- output))
+ (org-texinfo--prepend-anchor-maybe output drawer)))
;;;; Dynamic Block
-(defun org-texinfo-dynamic-block (_dynamic-block contents _info)
+(defun org-texinfo-dynamic-block (dynamic-block contents _info)
"Transcode a DYNAMIC-BLOCK element from Org to Texinfo.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- contents)
+ (org-texinfo--prepend-anchor-maybe contents dynamic-block))
;;;; Entity
@@ -1028,9 +1038,11 @@ (defun org-texinfo-example-block (example-block _contents info)
"Transcode an EXAMPLE-BLOCK element from Org to Texinfo.
CONTENTS is nil. INFO is a plist holding contextual
information."
- (format "@example\n%s@end example"
- (org-texinfo--sanitize-content
- (org-export-format-code-default example-block info))))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@example\n%s@end example"
+ (org-texinfo--sanitize-content
+ (org-export-format-code-default example-block info)))
+ example-block))
;;; Export Block
@@ -1053,10 +1065,12 @@ ;;;; Fixed Width
(defun org-texinfo-fixed-width (fixed-width _contents _info)
"Transcode a FIXED-WIDTH element from Org to Texinfo.
CONTENTS is nil. INFO is a plist holding contextual information."
- (format "@example\n%s\n@end example"
- (org-remove-indentation
- (org-texinfo--sanitize-content
- (org-element-property :value fixed-width)))))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@example\n%s\n@end example"
+ (org-remove-indentation
+ (org-texinfo--sanitize-content
+ (org-element-property :value fixed-width))))
+ fixed-width))
;;;; Footnote Reference
@@ -1274,11 +1288,13 @@ (defun org-texinfo-latex-environment (environment _contents info)
(when (or (eq with-latex t)
(and (eq with-latex 'detect)
(org-texinfo-supports-math-p)))
- (let ((value (org-element-property :value environment)))
- (string-join (list "@displaymath"
- (string-trim (org-remove-indentation value))
- "@end displaymath")
- "\n")))))
+ (org-texinfo--prepend-anchor-maybe
+ (let ((value (org-element-property :value environment)))
+ (string-join (list "@displaymath"
+ (string-trim (org-remove-indentation value))
+ "@end displaymath")
+ "\n"))
+ environment))))
;;;; LaTeX Fragment
@@ -1534,7 +1550,7 @@ (defun org-texinfo-node-property (node-property _contents _info)
;;;; Paragraph
-(defun org-texinfo-paragraph (_paragraph contents _info)
+(defun org-texinfo-paragraph (paragraph contents _info)
"Transcode a PARAGRAPH element from Org to Texinfo.
CONTENTS is the contents of the paragraph, as a string. INFO is
the plist used as a communication channel."
@@ -1543,7 +1559,9 @@ (defun org-texinfo-paragraph (_paragraph contents _info)
;; Multiple newlines may appear in CONTENTS, for example, when
;; certain objects are stripped from export, leaving single newlines
;; before and after.
- (org-remove-blank-lines contents))
+ (org-texinfo--prepend-anchor-maybe
+ (org-remove-blank-lines contents)
+ paragraph))
;;;; Plain List
@@ -1571,12 +1589,14 @@ (defun org-texinfo-plain-list (plain-list contents info)
((eq type 'unordered) "itemize")
((member table-type '("ftable" "vtable")) table-type)
(t "table"))))
- (format "@%s\n%s@end %s"
- (cond ((eq type 'descriptive) (concat list-type " " indic))
- (enum (format "%s %s" list-type enum))
- (t list-type))
- contents
- list-type)))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@%s\n%s@end %s"
+ (cond ((eq type 'descriptive) (concat list-type " " indic))
+ (enum (format "%s %s" list-type enum))
+ (t list-type))
+ contents
+ list-type)
+ plain-list)))
;;;; Plain Text
@@ -1662,10 +1682,12 @@ (defun org-texinfo-quote-block (quote-block contents _info)
holding contextual information."
(let ((tag (org-export-read-attribute :attr_texinfo quote-block :tag))
(author (org-export-read-attribute :attr_texinfo quote-block :author)))
- (format "@quotation%s\n%s%s\n@end quotation"
- (if tag (concat " " tag) "")
- contents
- (if author (concat "\n@author " author) ""))))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@quotation%s\n%s%s\n@end quotation"
+ (if tag (concat " " tag) "")
+ contents
+ (if author (concat "\n@author " author) ""))
+ quote-block)))
;;;; Radio Target
@@ -1702,11 +1724,13 @@ (defun org-texinfo-special-block (special-block contents _info)
(org-element-property :ox-texinfo--options special-block)
(org-export-read-attribute :attr_texinfo special-block :options)))
(type (org-element-property :type special-block)))
- (format "@%s%s\n%s@end %s"
- type
- (if opt (concat " " opt) "")
- (or contents "")
- type)))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@%s%s\n%s@end %s"
+ type
+ (if opt (concat " " opt) "")
+ (or contents "")
+ type)
+ special-block)))
;;;; Src Block
@@ -1724,13 +1748,15 @@ (defun org-texinfo-src-block (src-block _contents info)
code))
(caption (org-export-get-caption src-block))
(shortcaption (org-export-get-caption src-block t)))
- (if (not (or caption shortcaption)) value
+ (cond
+ ((or caption shortcaption)
(org-texinfo--wrap-float value
info
(org-export-translate "Listing" :utf-8 info)
- (org-texinfo--get-node src-block info)
+ (org-element-property :name src-block)
caption
- shortcaption))))
+ shortcaption))
+ (t (org-texinfo--prepend-anchor-maybe value src-block)))))
;;;; Statistics Cookie
@@ -1771,9 +1797,11 @@ (defun org-texinfo-table (table contents info)
CONTENTS is the contents of the table. INFO is a plist holding
contextual information."
(if (eq (org-element-property :type table) 'table.el)
- (format "@verbatim\n%s@end verbatim"
- (org-element-normalize-string
- (org-element-property :value table)))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@verbatim\n%s@end verbatim"
+ (org-element-normalize-string
+ (org-element-property :value table)))
+ table)
(let* ((col-width (org-export-read-attribute :attr_texinfo table :columns))
(columns
(if col-width (format "@columnfractions %s" col-width)
@@ -1783,13 +1811,15 @@ (defun org-texinfo-table (table contents info)
(table-str (format "@multitable %s\n%s@end multitable"
columns
contents)))
- (if (not (or caption shortcaption)) table-str
- (org-texinfo--wrap-float table-str
+ (cond
+ ((or caption shortcaption)
+ (org-texinfo--wrap-float table-str
info
(org-export-translate "Table" :utf-8 info)
- (org-texinfo--get-node table info)
+ (org-element-property :name table)
caption
- shortcaption)))))
+ shortcaption))
+ (t (org-texinfo--prepend-anchor-maybe table-str table))))))
(defun org-texinfo-table-column-widths (table info)
"Determine the largest table cell in each column to process alignment.
@@ -1891,11 +1921,13 @@ (defun org-texinfo-verbatim (verbatim _contents info)
;;;; Verse Block
-(defun org-texinfo-verse-block (_verse-block contents _info)
+(defun org-texinfo-verse-block (verse-block contents _info)
"Transcode a VERSE-BLOCK element from Org to Texinfo.
CONTENTS is verse block contents. INFO is a plist holding
contextual information."
- (format "@display\n%s@end display" contents))
+ (org-texinfo--prepend-anchor-maybe
+ (format "@display\n%s@end display" contents)
+ verse-block))
\f
;;; Public Functions
diff --git a/testing/lisp/test-ox-texinfo.el b/testing/lisp/test-ox-texinfo.el
index 681af7363e..6b6d16aea7 100644
--- a/testing/lisp/test-ox-texinfo.el
+++ b/testing/lisp/test-ox-texinfo.el
@@ -374,6 +374,56 @@ (ert-deftest test-ox-texinfo/references ()
(re-search-forward "@ref{B, , B}")
(re-search-forward "@ref{B, , C}")))))))
+(ert-deftest test-ox-texinfo/anchors ()
+ "Test anchors and references."
+ (should
+ (org-test-with-temp-text
+ (string-join
+ (list "* The document"
+ "** The model"
+ "This is some text describing the model."
+ "#+name: model"
+ "#+begin_src julia"
+ " struct Model"
+ " end"
+ "#+end_src"
+ "** Solution"
+ "Solving the model ([[model]]) leads to some interesting results."
+ )
+ "\n")
+ (let ((export-buffer "*Test Texinfo Export*")
+ (org-export-show-temporary-export-buffer nil))
+ (org-export-to-buffer 'texinfo export-buffer
+ nil nil nil nil nil
+ #'texinfo-mode)
+ (with-current-buffer export-buffer
+ (goto-char (point-min))
+ (and
+ (re-search-forward "@anchor{model}")
+ (re-search-forward "@ref{model}"))))))
+ (should
+ (org-test-with-temp-text
+ (string-join
+ (list "* The document"
+ "** The model"
+ "This is some text describing the model."
+ "#+name: model"
+ "| foo | bar |"
+ "** Solution"
+ "Solving the model ([[model]]) leads to some interesting results."
+ )
+ "\n")
+ (let ((export-buffer "*Test Texinfo Export*")
+ (org-export-show-temporary-export-buffer nil))
+ (org-export-to-buffer 'texinfo export-buffer
+ nil nil nil nil nil
+ #'texinfo-mode)
+ (with-current-buffer export-buffer
+ (goto-char (point-min))
+ (and
+ (re-search-forward "@anchor{model}")
+ (re-search-forward "@ref{model}")))))))
+
\f
;;; Headings with links
--
2.47.1
[-- Attachment #3: Type: text/plain, Size: 223 bytes --]
--
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply related [flat|nested] 4+ messages in thread