diff options
Diffstat (limited to 'lisp/org/ox-texinfo.el')
-rw-r--r-- | lisp/org/ox-texinfo.el | 111 |
1 files changed, 66 insertions, 45 deletions
diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el index 6e8d0d62141..8b949b361aa 100644 --- a/lisp/org/ox-texinfo.el +++ b/lisp/org/ox-texinfo.el @@ -2,6 +2,7 @@ ;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com> +;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com> ;; Keywords: outlines, hypermedia, calendar, wp ;; This file is part of GNU Emacs. @@ -420,8 +421,8 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" and (defun org-texinfo--normalize-headlines (tree _backend info) "Normalize headlines in TREE. -BACK-END is the symbol specifying back-end used for export. INFO -is a plist used as a communication channel. +BACK-END is the symbol specifying back-end used for export. +INFO is a plist used as a communication channel. Make sure every headline in TREE contains a section, since those are required to install a menu. Also put exactly one blank line @@ -489,16 +490,18 @@ node or anchor name is unique." ;; Org exports deeper elements before their parents. If two ;; node names collide -- e.g., they have the same title -- ;; within the same hierarchy, the second one would get the - ;; shorter node name. This is counter-intuitive. - ;; Consequently, we ensure that every parent headline get - ;; its node beforehand. As a recursive operation, this + ;; smaller node name. This is counter-intuitive. + ;; Consequently, we ensure that every parent headline gets + ;; its node beforehand. As a recursive operation, this ;; achieves the desired effect. (let ((parent (org-element-lineage datum '(headline)))) (when (and parent (not (assq parent cache))) (org-texinfo--get-node parent info) (setq cache (plist-get info :texinfo-node-cache)))) - ;; Ensure NAME is unique and not reserved node name "Top". - (while (or (equal name "Top") (rassoc name cache)) + ;; Ensure NAME is unique and not reserved node name "Top", + ;; no matter what case is used. + (while (or (string-equal "Top" (capitalize name)) + (rassoc name cache)) (setq name (concat basename (format " (%d)" (cl-incf salt))))) (plist-put info :texinfo-node-cache (cons (cons datum name) cache)) name)))) @@ -559,6 +562,14 @@ strings (e.g., returned by `org-export-get-caption')." (format "@float %s%s\n%s\n%s%s@end float" type (if label (concat "," label) "") value caption-str short-str))) +(defun org-texinfo--sectioning-structure (info) + "Return sectioning structure used in the document. +INFO is a plist holding export options." + (let ((class (plist-get info :texinfo-class))) + (pcase (assoc class (plist-get info :texinfo-classes)) + (`(,_ ,_ . ,sections) sections) + (_ (user-error "Unknown Texinfo class: %S" class))))) + ;;; Template (defun org-texinfo-template (contents info) @@ -838,9 +849,17 @@ CONTENTS is nil. INFO is a plist holding contextual information." FOOTNOTE is the footnote to define. CONTENTS is nil. INFO is a plist holding contextual information." - (let ((def (org-export-get-footnote-definition footnote info))) + (let* ((contents (org-export-get-footnote-definition footnote info)) + (data (org-export-data contents info))) (format "@footnote{%s}" - (org-trim (org-export-data def info))))) + ;; It is invalid to close a footnote on a line starting + ;; with "@end". As a safety net, we leave a newline + ;; character before the closing brace. However, when the + ;; footnote ends with a paragraph, it is visually pleasing + ;; to move the brace right after its end. + (if (eq 'paragraph (org-element-type (org-last contents))) + (org-trim data) + data)))) ;;;; Headline @@ -858,25 +877,22 @@ holding contextual information." (notoc? (org-export-excluded-from-toc-p headline info)) (command (and - (not (org-export-low-level-p headline info)) - (let ((class (plist-get info :texinfo-class))) - (pcase (assoc class (plist-get info :texinfo-classes)) - (`(,_ ,_ . ,sections) - (pcase (nth (1- (org-export-get-relative-level headline info)) - sections) - (`(,numbered ,unnumbered ,unnumbered-no-toc ,appendix) - (cond - ((org-not-nil - (org-export-get-node-property :APPENDIX headline t)) - appendix) - (numbered? numbered) - (index unnumbered) - (notoc? unnumbered-no-toc) - (t unnumbered))) - (`nil nil) - (_ (user-error "Invalid Texinfo class specification: %S" - class)))) - (_ (user-error "Unknown Texinfo class: %S" class)))))) + (not (org-export-low-level-p headline info)) + (let ((sections (org-texinfo--sectioning-structure info))) + (pcase (nth (1- (org-export-get-relative-level headline info)) + sections) + (`(,numbered ,unnumbered ,unnumbered-no-toc ,appendix) + (cond + ((org-not-nil + (org-export-get-node-property :APPENDIX headline t)) + appendix) + (numbered? numbered) + (index unnumbered) + (notoc? unnumbered-no-toc) + (t unnumbered))) + (`nil nil) + (_ (user-error "Invalid Texinfo class specification: %S" + (plist-get info :texinfo-class))))))) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) @@ -894,11 +910,12 @@ holding contextual information." (contents (concat "\n" (if (org-string-nw-p contents) (concat "\n" contents) "") - (and index (format "\n@printindex %s\n" index))))) + (and index (format "\n@printindex %s\n" index)))) + (node (org-texinfo--get-node headline info))) (if (not command) (concat (and (org-export-first-sibling-p headline info) (format "@%s\n" (if numbered? 'enumerate 'itemize))) - "@item\n" full-text "\n" + (format "@item\n@anchor{%s}%s\n" node full-text) contents (if (org-export-last-sibling-p headline info) (format "@end %s" (if numbered? 'enumerate 'itemize)) @@ -906,13 +923,12 @@ holding contextual information." (concat ;; Even if HEADLINE is using @subheading and al., leave an ;; anchor so cross-references in the Org document still work. - (format (if notoc? "@anchor{%s}\n" "@node %s\n") - (org-texinfo--get-node headline info)) + (format (if notoc? "@anchor{%s}\n" "@node %s\n") node) (format command full-text) contents)))))) (defun org-texinfo-format-headline-default-function - (todo _todo-type priority text tags) + (todo _todo-type priority text tags) "Default format function for a headline. See `org-texinfo-format-headline-function' for details." (concat (and todo (format "@strong{%s} " todo)) @@ -949,7 +965,7 @@ holding contextual information." todo todo-type priority title tags contents))) (defun org-texinfo-format-inlinetask-default-function - (todo _todo-type priority title tags contents) + (todo _todo-type priority title tags contents) "Default format function for inlinetasks. See `org-texinfo-format-inlinetask-function' for details." (let ((full-title @@ -1111,7 +1127,9 @@ current state of the export, as a plist." (path (org-element-property :path link)) (filename (file-name-sans-extension - (if (file-name-absolute-p path) (expand-file-name path) path))) + (if (file-name-absolute-p path) + (expand-file-name path) + (file-relative-name path)))) (extension (file-name-extension path)) (attributes (org-export-read-attribute :attr_texinfo parent)) (height (or (plist-get attributes :height) "")) @@ -1192,7 +1210,7 @@ a plist containing contextual information." ;; Colons are used as a separator between title and node ;; name. Remove them. (replace-regexp-in-string - "[ \t]+:+" "" + "[ \t]*:+" "" (org-texinfo--sanitize-title (org-export-get-alt-title h info) info))) (node (org-texinfo--get-node h info)) @@ -1215,12 +1233,15 @@ holding contextual information." :texinfo-entries-cache))) (cached-entries (gethash scope cache 'no-cache))) (if (not (eq cached-entries 'no-cache)) cached-entries - (puthash scope - (cl-remove-if - (lambda (h) - (org-not-nil (org-export-get-node-property :COPYING h t))) - (org-export-collect-headlines info 1 scope)) - cache)))) + (let* ((sections (org-texinfo--sectioning-structure info)) + (max-depth (length sections))) + (puthash scope + (cl-remove-if + (lambda (h) + (or (org-not-nil (org-export-get-node-property :COPYING h t)) + (< max-depth (org-export-get-relative-level h info)))) + (org-export-collect-headlines info 1 scope)) + cache))))) ;;;; Node Property @@ -1585,7 +1606,7 @@ channel." (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 +CONTENTS is verse block contents. INFO is a plist holding contextual information." (format "@display\n%s@end display" contents)) @@ -1594,7 +1615,7 @@ contextual information." ;;;###autoload (defun org-texinfo-export-to-texinfo - (&optional async subtreep visible-only body-only ext-plist) + (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to a Texinfo file. If narrowing is active in the current buffer, only export its @@ -1645,7 +1666,7 @@ Usage: emacs -batch -f org-texinfo-export-to-texinfo-batch INFILE OUTFILE" ;;;###autoload (defun org-texinfo-export-to-info - (&optional async subtreep visible-only body-only ext-plist) + (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to Texinfo then process through to INFO. If narrowing is active in the current buffer, only export its |