From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id MIwWFDd9aWe6eAAA62LTzQ:P1 (envelope-from ) for ; Mon, 23 Dec 2024 15:09:43 +0000 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id MIwWFDd9aWe6eAAA62LTzQ (envelope-from ) for ; Mon, 23 Dec 2024 16:09:43 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=posteo.net header.s=2017 header.b="dB/DlxbQ"; 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"; dmarc=pass (policy=none) header.from=posteo.net ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1734966578; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=f38lLtO3e/SF05AgWE9xYO75ZrY7bI/Dlf5ItLB+ty4=; b=gSrp8SWYY5ZAgySqgEIWM62x1BYoEmoVLIJtpFo73HVCCx2S9i7HqgIvRUnWcOWKnhicr2 LcV73OP9FAo21sirf2M0WpP/eMMgPAdFcYq/JGKxkmIpe3y3eeuyUEdiEC56m0tEjJJ0DY WMXGj3BmEDEupfGqFcbV6zGOobZlaKUKXxEP+MplSVe3Ce6tenmjGet7ptq46nauRl3SIZ zeYC/Jefct9NQauk5QHF4eDP3trkIOpa+9B9iyxR383fMOsH8v3H+RAAB7/7RzcaOfO4UI M8HKsJ4o2P4WD+drSjJH8wOvJdn8fTGVLpEqCrzylAvf3l0AMsq/yJ7wFYUx1Q== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=posteo.net header.s=2017 header.b="dB/DlxbQ"; 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"; dmarc=pass (policy=none) header.from=posteo.net ARC-Seal: i=1; s=key1; d=yhetil.org; t=1734966578; a=rsa-sha256; cv=none; b=gHDfEbHwZNSI5s5gGkH3cqwIa1Y2buOQyvNX+IeYUfM90z2SGxNwVIC4Z33WlSSmAd6kAr dwv33BECl68DdTzMrDRjtAkYAoHxVKw+JQ1va2lChoosPV/DMX1+0vYaFPH0GPnSnd2Gvp bvA28Im6O8bDlV+4Uvb4ARKcLRnEPJohq7I/h35IU1fa9GcgCYVRCWkj/S4RlUQOZwzhgt 7u/5wD9wL7ioq5fMUR3OmKNhJjV1HLmHDnUfycT5LhCOL9ML/d+Kf5M9LMcplfN2sKDiaX y6A/GrIuV9F3+63W/8dvj+nygyNHHvfgX07/WTfLfthTAhUx87D1HceKVBHqQg== 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 0D8971FECA for ; Mon, 23 Dec 2024 16:09:38 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tPk3C-0005kh-Jl; Mon, 23 Dec 2024 10:08:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tPk3A-0005kW-NA for emacs-orgmode@gnu.org; Mon, 23 Dec 2024 10:08:52 -0500 Received: from mout02.posteo.de ([185.67.36.66]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tPk36-00045v-S9 for emacs-orgmode@gnu.org; Mon, 23 Dec 2024 10:08:52 -0500 Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 2B78F240101 for ; Mon, 23 Dec 2024 16:08:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1734966525; bh=tw2Q7wERZdXVgEU/kbmYPeoVX3/ZmzXGpDJNPHMGSvo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type: From; b=dB/DlxbQSdBcpmV4FRO4wXV482qNatqBKoRNN0hFlZxPYmrcOcNrgeJYMzMppqSas 2hzoJgiJjRJjNE3swoCxE0VXQPTG1QcJEFHEKsJqqGQE/Hi045KuUg11pYVkOkvjr7 Hx2Bk91ONCaGoG3UHav5DyachyN8xwGkV6Uh+ACWywbKhcNIyu0ppcAad9PCd2CQ+h T74zvYTT4L/C84HkQb1kImUvIh/co4xH5QAAXZiKXp9IT4pF8AEqZq6ONXNd75wpS5 tQBJ6ic6M7llhOgYtVHB2ynzws6oWyVcwhsRYmUH0HPTqjhSx2fvj9X/x7WCt3Xfld cMtofZ5fdU1AQ== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4YH1cr4xQXz6twD; Mon, 23 Dec 2024 16:08:44 +0100 (CET) From: Ihor Radchenko To: "Fraga, Eric" Cc: Emacs Org mode mailing list Subject: Re: texinfo export has no targets for src blocks In-Reply-To: <87h676qr8n.fsf@ucl.ac.uk> References: <87h676qr8n.fsf@ucl.ac.uk> Date: Mon, 23 Dec 2024 15:10:12 +0000 Message-ID: <877c7ql9kb.fsf@localhost> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=185.67.36.66; envelope-from=yantar92@posteo.net; helo=mout02.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -8.88 X-Spam-Score: -8.88 X-Migadu-Queue-Id: 0D8971FECA X-Migadu-Scanner: mx10.migadu.com X-TUID: db2nqwcw5U67 --=-=-= Content-Type: text/plain "Fraga, Eric" 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) --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-ox-texinfo-Support-references-to-name-d-elements.patch >From 3055cf517ba665f00820a179299df4cb43333c9b Mon Sep 17 00:00:00 2001 Message-ID: <3055cf517ba665f00820a179299df4cb43333c9b.1734966481.git.yantar92@posteo.net> From: Ihor Radchenko 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 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)) ;;; 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}"))))))) + ;;; Headings with links -- 2.47.1 --=-=-= Content-Type: text/plain -- Ihor Radchenko // yantar92, Org mode maintainer, Learn more about Org mode at . Support Org development at , or support my work at --=-=-=--