diff options
Diffstat (limited to 'elpa/org-9.5.2/ox-texinfo.el')
-rw-r--r-- | elpa/org-9.5.2/ox-texinfo.el | 1757 |
1 files changed, 0 insertions, 1757 deletions
diff --git a/elpa/org-9.5.2/ox-texinfo.el b/elpa/org-9.5.2/ox-texinfo.el deleted file mode 100644 index 46077ec..0000000 --- a/elpa/org-9.5.2/ox-texinfo.el +++ /dev/null @@ -1,1757 +0,0 @@ -;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine -*- lexical-binding: t; -*- - -;; 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. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: -;; -;; See Org manual for details. - -;;; Code: - -(require 'cl-lib) -(require 'ox) - -(defvar orgtbl-exp-regexp) - - - -;;; Define Back-End - -(org-export-define-backend 'texinfo - '((bold . org-texinfo-bold) - (center-block . org-texinfo-center-block) - (clock . org-texinfo-clock) - (code . org-texinfo-code) - (drawer . org-texinfo-drawer) - (dynamic-block . org-texinfo-dynamic-block) - (entity . org-texinfo-entity) - (example-block . org-texinfo-example-block) - (export-block . org-texinfo-export-block) - (export-snippet . org-texinfo-export-snippet) - (fixed-width . org-texinfo-fixed-width) - (footnote-definition . org-texinfo-footnote-definition) - (footnote-reference . org-texinfo-footnote-reference) - (headline . org-texinfo-headline) - (inline-src-block . org-texinfo-inline-src-block) - (inlinetask . org-texinfo-inlinetask) - (italic . org-texinfo-italic) - (item . org-texinfo-item) - (keyword . org-texinfo-keyword) - (line-break . org-texinfo-line-break) - (link . org-texinfo-link) - (node-property . org-texinfo-node-property) - (paragraph . org-texinfo-paragraph) - (plain-list . org-texinfo-plain-list) - (plain-text . org-texinfo-plain-text) - (planning . org-texinfo-planning) - (property-drawer . org-texinfo-property-drawer) - (quote-block . org-texinfo-quote-block) - (radio-target . org-texinfo-radio-target) - (section . org-texinfo-section) - (special-block . org-texinfo-special-block) - (src-block . org-texinfo-src-block) - (statistics-cookie . org-texinfo-statistics-cookie) - (strike-through . org-texinfo-strike-through) - (subscript . org-texinfo-subscript) - (superscript . org-texinfo-superscript) - (table . org-texinfo-table) - (table-cell . org-texinfo-table-cell) - (table-row . org-texinfo-table-row) - (target . org-texinfo-target) - (template . org-texinfo-template) - (timestamp . org-texinfo-timestamp) - (underline . org-texinfo-underline) - (verbatim . org-texinfo-verbatim) - (verse-block . org-texinfo-verse-block)) - :filters-alist - '((:filter-headline . org-texinfo--filter-section-blank-lines) - (:filter-parse-tree . org-texinfo--normalize-headlines) - (:filter-section . org-texinfo--filter-section-blank-lines) - (:filter-final-output . org-texinfo--untabify)) - :menu-entry - '(?i "Export to Texinfo" - ((?t "As TEXI file" org-texinfo-export-to-texinfo) - (?i "As INFO file" org-texinfo-export-to-info) - (?o "As INFO file and open" - (lambda (a s v b) - (if a (org-texinfo-export-to-info t s v b) - (org-open-file (org-texinfo-export-to-info nil s v b))))))) - :options-alist - '((:texinfo-filename "TEXINFO_FILENAME" nil nil t) - (:texinfo-class "TEXINFO_CLASS" nil org-texinfo-default-class t) - (:texinfo-header "TEXINFO_HEADER" nil nil newline) - (:texinfo-post-header "TEXINFO_POST_HEADER" nil nil newline) - (:subtitle "SUBTITLE" nil nil parse) - (:subauthor "SUBAUTHOR" nil nil newline) - (:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t) - (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t) - (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t) - (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t) - ;; Other variables. - (:texinfo-classes nil nil org-texinfo-classes) - (:texinfo-format-headline-function nil nil org-texinfo-format-headline-function) - (:texinfo-node-description-column nil nil org-texinfo-node-description-column) - (:texinfo-active-timestamp-format nil nil org-texinfo-active-timestamp-format) - (:texinfo-inactive-timestamp-format nil nil org-texinfo-inactive-timestamp-format) - (:texinfo-diary-timestamp-format nil nil org-texinfo-diary-timestamp-format) - (:texinfo-link-with-unknown-path-format nil nil org-texinfo-link-with-unknown-path-format) - (:texinfo-tables-verbatim nil nil org-texinfo-tables-verbatim) - (:texinfo-table-scientific-notation nil nil org-texinfo-table-scientific-notation) - (:texinfo-table-default-markup nil nil org-texinfo-table-default-markup) - (:texinfo-text-markup-alist nil nil org-texinfo-text-markup-alist) - (:texinfo-format-drawer-function nil nil org-texinfo-format-drawer-function) - (:texinfo-format-inlinetask-function nil nil org-texinfo-format-inlinetask-function))) - - - -;;; User Configurable Variables - -(defgroup org-export-texinfo nil - "Options for exporting Org mode files to Texinfo." - :tag "Org Export Texinfo" - :version "24.4" - :package-version '(Org . "8.0") - :group 'org-export) - -;;;; Preamble - -(defcustom org-texinfo-coding-system nil - "Default document encoding for Texinfo output. - -If nil it will default to `buffer-file-coding-system'." - :group 'org-export-texinfo - :type 'coding-system) - -(defcustom org-texinfo-default-class "info" - "The default Texinfo class." - :group 'org-export-texinfo - :type '(string :tag "Texinfo class")) - -(defcustom org-texinfo-classes - '(("info" - "@documentencoding AUTO\n@documentlanguage AUTO" - ("@chapter %s" "@unnumbered %s" "@chapheading %s" "@appendix %s") - ("@section %s" "@unnumberedsec %s" "@heading %s" "@appendixsec %s") - ("@subsection %s" "@unnumberedsubsec %s" "@subheading %s" - "@appendixsubsec %s") - ("@subsubsection %s" "@unnumberedsubsubsec %s" "@subsubheading %s" - "@appendixsubsubsec %s"))) - "Alist of Texinfo classes and associated header and structure. -If #+TEXINFO_CLASS is set in the buffer, use its value and the -associated information. Here is the structure of a class -definition: - - (class-name - header-string - (numbered-1 unnumbered-1 unnumbered-no-toc-1 appendix-1) - (numbered-2 unnumbered-2 unnumbered-no-toc-2 appendix-2) - ...) - - -The header string ------------------ - -The header string is inserted in the header of the generated -document, right after \"@setfilename\" and \"@settitle\" -commands. - -If it contains the special string - - \"@documentencoding AUTO\" - -\"AUTO\" will be replaced with an appropriate coding system. See -`org-texinfo-coding-system' for more information. Likewise, if -the string contains the special string - - \"@documentlanguage AUTO\" - -\"AUTO\" will be replaced with the language defined in the -buffer, through #+LANGUAGE keyword, or globally, with -`org-export-default-language', which see. - - -The sectioning structure ------------------------- - -The sectioning structure of the class is given by the elements -following the header string. For each sectioning level, a number -of strings is specified. A %s formatter is mandatory in each -section string and will be replaced by the title of the section." - :group 'org-export-texinfo - :version "27.1" - :package-version '(Org . "9.2") - :type '(repeat - (list (string :tag "Texinfo class") - (string :tag "Texinfo header") - (repeat :tag "Levels" :inline t - (choice - (list :tag "Heading" - (string :tag " numbered") - (string :tag " unnumbered") - (string :tag "unnumbered-no-toc") - (string :tag " appendix"))))))) - -;;;; Headline - -(defcustom org-texinfo-format-headline-function - 'org-texinfo-format-headline-default-function - "Function to format headline text. - -This function will be called with 5 arguments: -TODO the todo keyword (string or nil). -TODO-TYPE the type of todo (symbol: `todo', `done', nil) -PRIORITY the priority of the headline (integer or nil) -TEXT the main headline text (string). -TAGS the tags as a list of strings (list of strings or nil). - -The function result will be used in the section format string." - :group 'org-export-texinfo - :type 'function - :version "26.1" - :package-version '(Org . "8.3")) - -;;;; Node listing (menu) - -(defcustom org-texinfo-node-description-column 32 - "Column at which to start the description in the node listings. -If a node title is greater than this length, the description will -be placed after the end of the title." - :group 'org-export-texinfo - :type 'integer) - -;;;; Timestamps - -(defcustom org-texinfo-active-timestamp-format "@emph{%s}" - "A printf format string to be applied to active timestamps." - :group 'org-export-texinfo - :type 'string) - -(defcustom org-texinfo-inactive-timestamp-format "@emph{%s}" - "A printf format string to be applied to inactive timestamps." - :group 'org-export-texinfo - :type 'string) - -(defcustom org-texinfo-diary-timestamp-format "@emph{%s}" - "A printf format string to be applied to diary timestamps." - :group 'org-export-texinfo - :type 'string) - -;;;; Links - -(defcustom org-texinfo-link-with-unknown-path-format "@indicateurl{%s}" - "Format string for links with unknown path type." - :group 'org-export-texinfo - :type 'string) - -;;;; Tables - -(defcustom org-texinfo-tables-verbatim nil - "When non-nil, tables are exported verbatim." - :group 'org-export-texinfo - :type 'boolean) - -(defcustom org-texinfo-table-scientific-notation nil - "Format string to display numbers in scientific notation. - -The format should have \"%s\" twice, for mantissa and exponent -\(i.e. \"%s\\\\times10^{%s}\"). - -When nil, no transformation is made." - :group 'org-export-texinfo - :type '(choice - (string :tag "Format string") - (const :tag "No formatting" nil))) - -(defcustom org-texinfo-table-default-markup "@asis" - "Default markup for first column in two-column tables. - -This should an indicating command, e.g., \"@code\", \"@kbd\" or -\"@samp\". - -It can be overridden locally using the \":indic\" attribute." - :group 'org-export-texinfo - :type 'string - :version "26.1" - :package-version '(Org . "9.1") - :safe #'stringp) - -;;;; Text markup - -(defcustom org-texinfo-text-markup-alist '((bold . "@strong{%s}") - (code . code) - (italic . "@emph{%s}") - (verbatim . samp)) - "Alist of Texinfo expressions to convert text markup. - -The key must be a symbol among `bold', `code', `italic', -`strike-through', `underscore' and `verbatim'. The value is -a formatting string to wrap fontified text with. - -Value can also be set to the following symbols: `verb', `samp' -and `code'. With the first one, Org uses \"@verb\" to create -a format string and selects a delimiter character that isn't in -the string. For the other two, Org uses \"@samp\" or \"@code\" -to typeset and protects special characters. - -When no association is found for a given markup, text is returned -as-is." - :group 'org-export-texinfo - :version "26.1" - :package-version '(Org . "9.1") - :type 'alist - :options '(bold code italic strike-through underscore verbatim)) - -;;;; Drawers - -(defcustom org-texinfo-format-drawer-function (lambda (_name contents) contents) - "Function called to format a drawer in Texinfo code. - -The function must accept two parameters: - NAME the drawer name, like \"LOGBOOK\" - CONTENTS the contents of the drawer. - -The function should return the string to be exported. - -The default function simply returns the value of CONTENTS." - :group 'org-export-texinfo - :version "24.4" - :package-version '(Org . "8.2") - :type 'function) - -;;;; Inlinetasks - -(defcustom org-texinfo-format-inlinetask-function - 'org-texinfo-format-inlinetask-default-function - "Function called to format an inlinetask in Texinfo code. - -The function must accept six parameters: - TODO the todo keyword, as a string - TODO-TYPE the todo type, a symbol among `todo', `done' and nil. - PRIORITY the inlinetask priority, as a string - NAME the inlinetask name, as a string. - TAGS the inlinetask tags, as a list of strings. - CONTENTS the contents of the inlinetask, as a string. - -The function should return the string to be exported." - :group 'org-export-texinfo - :type 'function) - -;;;; Compilation - -(defcustom org-texinfo-info-process '("makeinfo --no-split %f") - "Commands to process a Texinfo file to an INFO file. - -This is a list of strings, each of them will be given to the -shell as a command. %f in the command will be replaced by the -relative file name, %F by the absolute file name, %b by the file -base name (i.e. without directory and extension parts), %o by the -base directory of the file and %O by the absolute file name of -the output file." - :group 'org-export-texinfo - :version "26.1" - :package-version '(Org . "9.1") - :type '(repeat :tag "Shell command sequence" - (string :tag "Shell command"))) - -(defcustom org-texinfo-logfiles-extensions - '("aux" "toc" "cp" "fn" "ky" "pg" "tp" "vr") - "The list of file extensions to consider as Texinfo logfiles. -The logfiles will be remove if `org-texinfo-remove-logfiles' is -non-nil." - :group 'org-export-texinfo - :type '(repeat (string :tag "Extension"))) - -(defcustom org-texinfo-remove-logfiles t - "Non-nil means remove the logfiles produced by compiling a Texinfo file. -By default, logfiles are files with these extensions: .aux, .toc, -.cp, .fn, .ky, .pg and .tp. To define the set of logfiles to remove, -set `org-texinfo-logfiles-extensions'." - :group 'org-export-latex - :type 'boolean) - -;;; Constants - -(defconst org-texinfo-max-toc-depth 4 - "Maximum depth for creation of detailed menu listings. -Beyond this depth, Texinfo will not recognize the nodes and will -cause errors. Left as a constant in case this value ever -changes.") - -(defconst org-texinfo-supported-coding-systems - '("US-ASCII" "UTF-8" "ISO-8859-15" "ISO-8859-1" "ISO-8859-2" "koi8-r" "koi8-u") - "List of coding systems supported by Texinfo, as strings. -Specified coding system will be matched against these strings. -If two strings share the same prefix (e.g. \"ISO-8859-1\" and -\"ISO-8859-15\"), the most specific one has to be listed first.") - -(defconst org-texinfo-inline-image-rules - (list (cons "file" - (regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg")))) - "Rules characterizing image files that can be inlined.") - - -;;; Internal Functions - -(defun org-texinfo--untabify (s _backend _info) - "Remove TAB characters in string S." - (replace-regexp-in-string "\t" (make-string tab-width ?\s) s)) - -(defun org-texinfo--filter-section-blank-lines (headline _backend _info) - "Filter controlling number of blank lines after a section." - (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline)) - -(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. - -Make sure every headline in TREE contains a section, since those -are required to install a menu. Also put exactly one blank line -at the end of each section. - -Return new tree." - (org-element-map tree 'headline - (lambda (hl) - (org-element-put-property hl :post-blank 1) - (let ((contents (org-element-contents hl))) - (when contents - (let ((first (org-element-map contents '(headline section) - #'identity info t))) - (unless (eq (org-element-type first) 'section) - (apply #'org-element-set-contents - hl - (cons `(section (:parent ,hl)) contents))))))) - info) - tree) - -(defun org-texinfo--find-verb-separator (s) - "Return a character not used in string S. -This is used to choose a separator for constructs like \\verb." - (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) - (cl-loop for c across ll - when (not (string-match (regexp-quote (char-to-string c)) s)) - return (char-to-string c)))) - -(defun org-texinfo--text-markup (text markup _info) - "Format TEXT depending on MARKUP text markup. -INFO is a plist used as a communication channel. See -`org-texinfo-text-markup-alist' for details." - (pcase (cdr (assq markup org-texinfo-text-markup-alist)) - (`nil text) ;no markup: return raw text - (`code (format "@code{%s}" (org-texinfo--sanitize-content text))) - (`samp (format "@samp{%s}" (org-texinfo--sanitize-content text))) - (`verb - (let ((separator (org-texinfo--find-verb-separator text))) - (format "@verb{%s%s%s}" separator text separator))) - ;; Else use format string. - (fmt (format fmt text)))) - -(defun org-texinfo--get-node (datum info) - "Return node or anchor associated to DATUM. -DATUM is a headline, a radio-target or a target. INFO is a plist -used as a communication channel. The function guarantees the -node or anchor name is unique." - (let ((cache (plist-get info :texinfo-node-cache))) - (or (cdr (assq datum cache)) - (let* ((salt 0) - (basename - (org-texinfo--sanitize-node - (pcase (org-element-type datum) - (`headline - (org-texinfo--sanitize-title - (org-export-get-alt-title datum info) info)) - (`radio-target - (org-export-data (org-element-contents datum) info)) - (`target - (org-element-property :value datum)) - (_ - (or (org-element-property :name datum) - (org-export-get-reference datum info)))))) - (name basename)) - ;; 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 - ;; 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", - ;; 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)))) - -(defun org-texinfo--sanitize-node (title) - "Bend string TITLE to node line requirements. -Trim string and collapse multiple whitespace characters as they -are not significant. Replace leading left parenthesis, when -followed by a right parenthesis, with a square bracket. Remove -periods, commas and colons." - (org-trim - (replace-regexp-in-string - "[ \t]+" " " - (replace-regexp-in-string - "[:,.]" "" - (replace-regexp-in-string "\\`(\\(.*?)\\)" "[\\1" title))))) - -(defun org-texinfo--sanitize-title (title info) - "Make TITLE suitable as a section name. -TITLE is a string or a secondary string. INFO is the current -export state, as a plist." - (org-export-data-with-backend - title (org-export-toc-entry-backend 'texinfo) info)) - -(defun org-texinfo--sanitize-content (text) - "Escape special characters in string TEXT. -Special characters are: @ { }" - (replace-regexp-in-string "[@{}]" "@\\&" text)) - -(defun org-texinfo--wrap-float (value info &optional type label caption short) - "Wrap string VALUE within a @float command. -INFO is the current export state, as a plist. TYPE is float -type, as a string. LABEL is the cross reference label for the -float, as a string. CAPTION and SHORT are, respectively, the -caption and shortcaption used for the float, as secondary -strings (e.g., returned by `org-export-get-caption')." - (let* ((backend - (org-export-toc-entry-backend 'texinfo - (cons 'footnote-reference - (lambda (f c i) (org-export-with-backend 'texinfo f c i))))) - (short-backend - (org-export-toc-entry-backend 'texinfo - '(inline-src-block . ignore) - '(verbatim . ignore))) - (short-str - (if (and short caption) - (format "@shortcaption{%s}\n" - (org-export-data-with-backend short short-backend info)) - "")) - (caption-str - (if (or short caption) - (format "@caption{%s}\n" - (org-export-data-with-backend - (or caption short) - (if (equal short-str "") short-backend backend) - info)) - ""))) - (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) - "Return complete document string after Texinfo conversion. -CONTENTS is the transcoded contents string. INFO is a plist -holding export options." - (let ((title (org-export-data (plist-get info :title) info)) - ;; Copying data is the contents of the first headline in - ;; parse tree with a non-nil copying property. - (copying (org-element-map (plist-get info :parse-tree) 'headline - (lambda (hl) - (and (org-not-nil (org-element-property :COPYING hl)) - (org-element-contents hl))) - info t))) - (concat - "\\input texinfo @c -*- texinfo -*-\n" - "@c %**start of header\n" - (let ((file (or (org-strip-quotes (plist-get info :texinfo-filename)) - (let ((f (plist-get info :output-file))) - (and f (concat (file-name-sans-extension f) ".info")))))) - (and file (format "@setfilename %s\n" file))) - (format "@settitle %s\n" title) - ;; Insert class-defined header. - (org-element-normalize-string - (let ((header (nth 1 (assoc (plist-get info :texinfo-class) - org-texinfo-classes))) - (coding - (catch 'coding-system - (let ((case-fold-search t) - (name (symbol-name (or org-texinfo-coding-system - buffer-file-coding-system)))) - (dolist (system org-texinfo-supported-coding-systems "UTF-8") - (when (string-match-p (regexp-quote system) name) - (throw 'coding-system system)))))) - (language (plist-get info :language)) - (case-fold-search nil)) - ;; Auto coding system. - (replace-regexp-in-string - "^@documentencoding \\(AUTO\\)$" - coding - (replace-regexp-in-string - "^@documentlanguage \\(AUTO\\)$" language header t nil 1) - t nil 1))) - ;; Additional header options set by #+TEXINFO_HEADER. - (let ((texinfo-header (plist-get info :texinfo-header))) - (and texinfo-header (org-element-normalize-string texinfo-header))) - "@c %**end of header\n\n" - ;; Additional options set by #+TEXINFO_POST_HEADER. - (let ((texinfo-post-header (plist-get info :texinfo-post-header))) - (and texinfo-post-header - (org-element-normalize-string texinfo-post-header))) - ;; Copying. - (and copying - (format "@copying\n%s@end copying\n\n" - (org-element-normalize-string - (org-export-data copying info)))) - ;; Info directory information. Only supply if both title and - ;; category are provided. - (let ((dircat (plist-get info :texinfo-dircat)) - (dirtitle - (let ((title (plist-get info :texinfo-dirtitle))) - (and title - (string-match "^\\(?:\\* \\)?\\(.*?\\)\\(\\.\\)?$" title) - (format "* %s." (match-string 1 title)))))) - (when (and dircat dirtitle) - (concat "@dircategory " dircat "\n" - "@direntry\n" - (let ((dirdesc - (let ((desc (plist-get info :texinfo-dirdesc))) - (cond ((not desc) nil) - ((string-suffix-p "." desc) desc) - (t (concat desc ".")))))) - (if dirdesc (format "%-23s %s" dirtitle dirdesc) dirtitle)) - "\n" - "@end direntry\n\n"))) - ;; Title - "@finalout\n" - "@titlepage\n" - (when (plist-get info :with-title) - (concat - (format "@title %s\n" - (or (plist-get info :texinfo-printed-title) title "")) - (let ((subtitle (plist-get info :subtitle))) - (when subtitle - (format "@subtitle %s\n" - (org-export-data subtitle info)))))) - (when (plist-get info :with-author) - (concat - ;; Primary author. - (let ((author (org-string-nw-p - (org-export-data (plist-get info :author) info))) - (email (and (plist-get info :with-email) - (org-string-nw-p - (org-export-data (plist-get info :email) info))))) - (cond ((and author email) - (format "@author %s (@email{%s})\n" author email)) - (author (format "@author %s\n" author)) - (email (format "@author @email{%s}\n" email)))) - ;; Other authors. - (let ((subauthor (plist-get info :subauthor))) - (and subauthor - (org-element-normalize-string - (replace-regexp-in-string "^" "@author " subauthor)))))) - (and copying "@page\n@vskip 0pt plus 1filll\n@insertcopying\n") - "@end titlepage\n\n" - ;; Table of contents. - (and (plist-get info :with-toc) "@contents\n\n") - ;; Configure Top Node when not for TeX. Also include contents - ;; from the first section of the document. - "@ifnottex\n" - "@node Top\n" - (format "@top %s\n" title) - (let* ((first-section - (org-element-map (plist-get info :parse-tree) 'section - #'identity info t '(headline))) - (top-contents - (org-export-data (org-element-contents first-section) info))) - (and (org-string-nw-p top-contents) (concat "\n" top-contents))) - "@end ifnottex\n\n" - ;; Menu. - (org-texinfo-make-menu (plist-get info :parse-tree) info 'master) - "\n" - ;; Document's body. - contents "\n" - ;; Creator. - (and (plist-get info :with-creator) - (concat (plist-get info :creator) "\n")) - ;; Document end. - "@bye"))) - - - -;;; Transcode Functions - -;;;; Bold - -(defun org-texinfo-bold (_bold contents info) - "Transcode BOLD from Org to Texinfo. -CONTENTS is the text with bold markup. INFO is a plist holding -contextual information." - (org-texinfo--text-markup contents 'bold info)) - -;;;; Center Block - -(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)) - -;;;; Clock - -(defun org-texinfo-clock (clock _contents info) - "Transcode a CLOCK element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - (concat - "@noindent" - (format "@strong{%s} " org-clock-string) - (format (plist-get info :texinfo-inactive-timestamp-format) - (concat (org-timestamp-translate (org-element-property :value clock)) - (let ((time (org-element-property :duration clock))) - (and time (format " (%s)" time))))) - "@*")) - -;;;; Code - -(defun org-texinfo-code (code _contents info) - "Transcode a CODE object from Org to Texinfo. -CONTENTS is nil. INFO is a plist used as a communication -channel." - (org-texinfo--text-markup (org-element-property :value code) 'code info)) - -;;;; Drawer - -(defun org-texinfo-drawer (drawer contents info) - "Transcode a DRAWER element from Org to Texinfo. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let* ((name (org-element-property :drawer-name drawer)) - (output (funcall (plist-get info :texinfo-format-drawer-function) - name contents))) - output)) - -;;;; Dynamic Block - -(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) - -;;;; Entity - -(defun org-texinfo-entity (entity _contents _info) - "Transcode an ENTITY object from Org to Texinfo." - ;; Since there is not specific Texinfo entry in entities, use - ;; Texinfo-specific commands whenever possible, and fallback to - ;; UTF-8 otherwise. - (pcase (org-element-property :name entity) - ("AElig" "@AE{}") - ("aelig" "@ae{}") - ((or "bull" "bullet") "@bullet{}") - ("copy" "@copyright{}") - ("deg" "@textdegree{}") - ((or "dots" "hellip") "@dots{}") - ("equiv" "@equiv{}") - ((or "euro" "EUR") "@euro{}") - ((or "ge" "geq") "@geq{}") - ("laquo" "@guillemetleft{}") - ("iexcl" "@exclamdown{}") - ("imath" "@dotless{i}") - ("iquest" "@questiondown{}") - ("jmath" "@dotless{j}") - ((or "le" "leq") "@leq{}") - ("lsaquo" "@guilsinglleft{}") - ("mdash" "---") - ("minus" "@minus{}") - ("nbsp" "@tie{}") - ("ndash" "--") - ("OElig" "@OE{}") - ("oelig" "@oe{}") - ("ordf" "@ordf{}") - ("ordm" "@ordm{}") - ("pound" "@pound{}") - ("raquo" "@guillemetright{}") - ((or "rArr" "Rightarrow") "@result{}") - ("reg" "@registeredsymbol{}") - ((or "rightarrow" "to" "rarr") "@arrow{}") - ("rsaquo" "@guilsinglright{}") - ("thorn" "@th{}") - ("THORN" "@TH{}") - ((and (pred (string-prefix-p "_")) name) ;spacing entities - (format "@w{%s}" (substring name 1))) - (_ (org-element-property :utf-8 entity)))) - -;;;; Example Block - -(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)))) - -;;; Export Block - -(defun org-texinfo-export-block (export-block _contents _info) - "Transcode a EXPORT-BLOCK element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (string= (org-element-property :type export-block) "TEXINFO") - (org-remove-indentation (org-element-property :value export-block)))) - -;;; Export Snippet - -(defun org-texinfo-export-snippet (export-snippet _contents _info) - "Transcode a EXPORT-SNIPPET object from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (eq (org-export-snippet-backend export-snippet) 'texinfo) - (org-element-property :value export-snippet))) - -;;;; 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))))) - -;;;; Footnote Reference - -(defun org-texinfo-footnote-reference (footnote _contents info) - "Create a footnote reference for FOOTNOTE. - -FOOTNOTE is the footnote to define. CONTENTS is nil. INFO is a -plist holding contextual information." - (let* ((contents (org-export-get-footnote-definition footnote info)) - (data (org-export-data contents info))) - (format "@footnote{%s}" - ;; 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 - -(defun org-texinfo-headline (headline contents info) - "Transcode a HEADLINE element from Org to Texinfo. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (cond - ((org-element-property :footnote-section-p headline) nil) - ((org-not-nil (org-export-get-node-property :COPYING headline t)) nil) - (t - (let* ((index (let ((i (org-export-get-node-property :INDEX headline t))) - (and (member i '("cp" "fn" "ky" "pg" "tp" "vr")) i))) - (numbered? (org-export-numbered-headline-p headline info)) - (notoc? (org-export-excluded-from-toc-p headline info)) - (command - (and - (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))) - (and todo (org-export-data todo info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (tags (and (plist-get info :with-tags) - (org-export-get-tags headline info))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (text (org-texinfo--sanitize-title - (org-element-property :title headline) info)) - (full-text - (funcall (plist-get info :texinfo-format-headline-function) - todo todo-type priority text tags)) - (contents - (concat "\n" - (if (org-string-nw-p contents) (concat "\n" contents) "") - (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))) - (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)) - "\n")) - (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") node) - (format command full-text) - contents)))))) - -(defun org-texinfo-format-headline-default-function - (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)) - (and priority (format "@emph{#%s} " priority)) - text - (and tags (concat " " (org-make-tag-string tags))))) - -;;;; Inline Src Block - -(defun org-texinfo-inline-src-block (inline-src-block _contents _info) - "Transcode an INLINE-SRC-BLOCK element from Org to Texinfo. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (format "@code{%s}" - (org-texinfo--sanitize-content - (org-element-property :value inline-src-block)))) - -;;;; Inlinetask - -(defun org-texinfo-inlinetask (inlinetask contents info) - "Transcode an INLINETASK element from Org to Texinfo. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((title (org-export-data (org-element-property :title inlinetask) info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property :todo-keyword inlinetask))) - (and todo (org-export-data todo info))))) - (todo-type (org-element-property :todo-type inlinetask)) - (tags (and (plist-get info :with-tags) - (org-export-get-tags inlinetask info))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority inlinetask)))) - (funcall (plist-get info :texinfo-format-inlinetask-function) - todo todo-type priority title tags contents))) - -(defun org-texinfo-format-inlinetask-default-function - (todo _todo-type priority title tags contents) - "Default format function for inlinetasks. -See `org-texinfo-format-inlinetask-function' for details." - (let ((full-title - (concat (when todo (format "@strong{%s} " todo)) - (when priority (format "#%c " priority)) - title - (when tags (org-make-tag-string tags))))) - (format "@center %s\n\n%s\n" full-title contents))) - -;;;; Italic - -(defun org-texinfo-italic (_italic contents info) - "Transcode ITALIC from Org to Texinfo. -CONTENTS is the text with italic markup. INFO is a plist holding -contextual information." - (org-texinfo--text-markup contents 'italic info)) - -;;;; Item - -(defun org-texinfo-item (item contents info) - "Transcode an ITEM element from Org to Texinfo. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((tag (org-element-property :tag item)) - (split (org-string-nw-p - (org-export-read-attribute :attr_texinfo - (org-element-property :parent item) - :sep))) - (items (and tag - (let ((tag (org-export-data tag info))) - (if split - (split-string tag (regexp-quote split) t "[ \t\n]+") - (list tag)))))) - (format "%s\n%s" - (pcase items - (`nil "@item") - (`(,item) (concat "@item " item)) - (`(,item . ,items) - (concat "@item " item "\n" - (mapconcat (lambda (i) (concat "@itemx " i)) - items - "\n")))) - (or contents "")))) - -;;;; Keyword - -(defun org-texinfo-keyword (keyword _contents info) - "Transcode a KEYWORD element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-element-property :value keyword))) - (pcase (org-element-property :key keyword) - ("TEXINFO" value) - ("CINDEX" (format "@cindex %s" value)) - ("FINDEX" (format "@findex %s" value)) - ("KINDEX" (format "@kindex %s" value)) - ("PINDEX" (format "@pindex %s" value)) - ("TINDEX" (format "@tindex %s" value)) - ("VINDEX" (format "@vindex %s" value)) - ("TOC" - (cond ((string-match-p "\\<tables\\>" value) - (concat "@listoffloats " - (org-export-translate "Table" :utf-8 info))) - ((string-match-p "\\<listings\\>" value) - (concat "@listoffloats " - (org-export-translate "Listing" :utf-8 info)))))))) - -;;;; Line Break - -(defun org-texinfo-line-break (_line-break _contents _info) - "Transcode a LINE-BREAK object from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - "@*\n") - -;;;; Link - -(defun org-texinfo--@ref (datum description info) - "Return @ref command for element or object DATUM. -DESCRIPTION is the printed name of the section, as a string, or -nil." - (let ((node-name (org-texinfo--get-node datum info)) - ;; Sanitize DESCRIPTION for cross-reference use. In - ;; particular, remove colons as they seem to cause pain (even - ;; within @asis{...}) to the Texinfo reader. - (title (and description - (replace-regexp-in-string - "[ \t]*:+" "" - (replace-regexp-in-string "," "@comma{}" description))))) - (if (or (not title) (equal title node-name)) - (format "@ref{%s}" node-name) - (format "@ref{%s, , %s}" node-name title)))) - -(defun org-texinfo-link (link desc info) - "Transcode a LINK object from Org to Texinfo. -DESC is the description part of the link, or the empty string. -INFO is a plist holding contextual information. See -`org-export-data'." - (let* ((type (org-element-property :type link)) - (raw-path (org-element-property :path link)) - ;; Ensure DESC really exists, or set it to nil. - (desc (and (not (string= desc "")) desc)) - (path (org-texinfo--sanitize-content - (cond - ((member type '("http" "https" "ftp")) - (concat type ":" raw-path)) - ((string-equal type "file") - (org-export-file-uri raw-path)) - (t raw-path))))) - (cond - ((org-export-custom-protocol-maybe link desc 'texinfo info)) - ((org-export-inline-image-p link org-texinfo-inline-image-rules) - (org-texinfo--inline-image link info)) - ((equal type "radio") - (let ((destination (org-export-resolve-radio-link link info))) - (if (not destination) desc - (org-texinfo--@ref destination desc info)))) - ((member type '("custom-id" "id" "fuzzy")) - (let ((destination - (if (equal type "fuzzy") - (org-export-resolve-fuzzy-link link info) - (org-export-resolve-id-link link info)))) - (pcase (org-element-type destination) - (`nil - (format org-texinfo-link-with-unknown-path-format path)) - ;; Id link points to an external file. - (`plain-text - (if desc (format "@uref{file://%s,%s}" destination desc) - (format "@uref{file://%s}" destination))) - ((or `headline - ;; Targets within headlines cannot be turned into - ;; @anchor{}, so we refer to the headline parent - ;; directly. - (and `target - (guard (eq 'headline - (org-element-type - (org-element-property :parent destination)))))) - (let ((headline (org-element-lineage destination '(headline) t))) - (org-texinfo--@ref headline desc info))) - (_ (org-texinfo--@ref destination desc info))))) - ((string= type "mailto") - (format "@email{%s}" - (concat path (and desc (concat ", " desc))))) - ;; External link with a description part. - ((and path desc) (format "@uref{%s, %s}" path desc)) - ;; External link without a description part. - (path (format "@uref{%s}" path)) - ;; No path, only description. Try to do something useful. - (t - (format (plist-get info :texinfo-link-with-unknown-path-format) desc))))) - -(defun org-texinfo--inline-image (link info) - "Return Texinfo code for an inline image. -LINK is the link pointing to the inline image. INFO is the -current state of the export, as a plist." - (let* ((parent (org-export-get-parent-element link)) - (label (and (org-element-property :name parent) - (org-texinfo--get-node parent info))) - (caption (org-export-get-caption parent)) - (shortcaption (org-export-get-caption parent t)) - (path (org-element-property :path link)) - (filename - (file-name-sans-extension - (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) "")) - (width (or (plist-get attributes :width) "")) - (alt (or (plist-get attributes :alt) "")) - (image (format "@image{%s,%s,%s,%s,%s}" - filename width height alt extension))) - (cond ((or caption shortcaption) - (org-texinfo--wrap-float image - info - (org-export-translate "Figure" :utf-8 info) - label - caption - shortcaption)) - (label (concat "@anchor{" label "}\n" image)) - (t image)))) - - -;;;; Menu - -(defun org-texinfo-make-menu (scope info &optional master) - "Create the menu for inclusion in the Texinfo document. - -SCOPE is a headline or a full parse tree. INFO is the -communication channel, as a plist. - -When optional argument MASTER is non-nil, generate a master menu, -including detailed node listing." - (let ((menu (org-texinfo--build-menu scope info))) - (when (org-string-nw-p menu) - (org-element-normalize-string - (format - "@menu\n%s@end menu" - (concat menu - (when master - (let ((detailmenu - (org-texinfo--build-menu - scope info - (let ((toc-depth (plist-get info :with-toc))) - (if (wholenump toc-depth) toc-depth - org-texinfo-max-toc-depth))))) - (when (org-string-nw-p detailmenu) - (concat "\n@detailmenu\n" - "--- The Detailed Node Listing ---\n\n" - detailmenu - "@end detailmenu\n")))))))))) - -(defun org-texinfo--build-menu (scope info &optional level) - "Build menu for entries within SCOPE. -SCOPE is a headline or a full parse tree. INFO is a plist -containing contextual information. When optional argument LEVEL -is an integer, build the menu recursively, down to this depth." - (cond - ((not level) - (org-texinfo--format-entries (org-texinfo--menu-entries scope info) info)) - ((zerop level) "\n") - (t - (mapconcat - (lambda (h) - (let ((entries (org-texinfo--menu-entries h info))) - (when entries - (concat - (format "%s\n\n%s\n" - (org-export-data (org-export-get-alt-title h info) info) - (org-texinfo--format-entries entries info)) - (org-texinfo--build-menu h info (1- level)))))) - (org-texinfo--menu-entries scope info) - "")))) - -(defun org-texinfo--format-entries (entries info) - "Format all direct menu entries in SCOPE, as a string. -SCOPE is either a headline or a full Org document. INFO is -a plist containing contextual information." - (org-element-normalize-string - (mapconcat - (lambda (h) - (let* ((title - ;; Colons are used as a separator between title and node - ;; name. Remove them. - (replace-regexp-in-string - "[ \t]*:+" "" - (org-texinfo--sanitize-title - (org-export-get-alt-title h info) info))) - (node (org-texinfo--get-node h info)) - (entry (concat "* " title ":" - (if (string= title node) ":" - (concat " " node ". ")))) - (desc (org-element-property :DESCRIPTION h))) - (if (not desc) entry - (format (format "%%-%ds %%s" org-texinfo-node-description-column) - entry desc)))) - entries "\n"))) - -(defun org-texinfo--menu-entries (scope info) - "List direct children in SCOPE needing a menu entry. -SCOPE is a headline or a full parse tree. INFO is a plist -holding contextual information." - (let* ((cache (or (plist-get info :texinfo-entries-cache) - (plist-get (plist-put info :texinfo-entries-cache - (make-hash-table :test #'eq)) - :texinfo-entries-cache))) - (cached-entries (gethash scope cache 'no-cache))) - (if (not (eq cached-entries 'no-cache)) cached-entries - (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 - -(defun org-texinfo-node-property (node-property _contents _info) - "Transcode a NODE-PROPERTY element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - (format "%s:%s" - (org-element-property :key node-property) - (let ((value (org-element-property :value node-property))) - (if value (concat " " value) "")))) - -;;;; Paragraph - -(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." - contents) - -;;;; Plain List - -(defun org-texinfo-plain-list (plain-list contents info) - "Transcode a PLAIN-LIST element from Org to Texinfo. -CONTENTS is the contents of the list. INFO is a plist holding -contextual information." - (let* ((attr (org-export-read-attribute :attr_texinfo plain-list)) - (indic (let ((i (or (plist-get attr :indic) - (plist-get info :texinfo-table-default-markup)))) - ;; Allow indicating commands with missing @ sign. - (if (string-prefix-p "@" i) i (concat "@" i)))) - (table-type (plist-get attr :table-type)) - (type (org-element-property :type plain-list)) - (enum - (cond ((not (eq type 'ordered)) nil) - ((plist-member attr :enum) (plist-get attr :enum)) - (t - ;; Texinfo only supports initial counters, i.e., it - ;; cannot change the numbering mid-list. - (let ((first-item (car (org-element-contents plain-list)))) - (org-element-property :counter first-item))))) - (list-type (cond - ((eq type 'ordered) "enumerate") - ((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))) - -;;;; Plain Text - -(defun org-texinfo-plain-text (text info) - "Transcode a TEXT string from Org to Texinfo. -TEXT is the string to transcode. INFO is a plist holding -contextual information." - ;; First protect @, { and }. - (let ((output (org-texinfo--sanitize-content text))) - ;; Activate smart quotes. Be sure to provide original TEXT string - ;; since OUTPUT may have been modified. - (when (plist-get info :with-smart-quotes) - (setq output - (org-export-activate-smart-quotes output :texinfo info text))) - ;; LaTeX into @LaTeX{} and TeX into @TeX{} - (let ((case-fold-search nil)) - (setq output (replace-regexp-in-string "\\(?:La\\)?TeX" "@\\&{}" output))) - ;; Convert special strings. - (when (plist-get info :with-special-strings) - (setq output - (replace-regexp-in-string - "\\.\\.\\." "@dots{}" - (replace-regexp-in-string "\\\\-" "@-" output)))) - ;; Handle break preservation if required. - (when (plist-get info :preserve-breaks) - (setq output (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" " @*\n" output))) - ;; Reverse sentence ending. A sentence can end with a capital - ;; letter. Use non-breaking space if it shouldn't. - (let ((case-fold-search nil)) - (replace-regexp-in-string - "[A-Z]\\([.?!]\\)\\(?:[])]\\|'\\{1,2\\}\\)?\\(?: \\|$\\)" - "@\\1" - output nil nil 1)))) - -;;;; Planning - -(defun org-texinfo-planning (planning _contents info) - "Transcode a PLANNING element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - (concat - "@noindent" - (mapconcat - 'identity - (delq nil - (list - (let ((closed (org-element-property :closed planning))) - (when closed - (concat - (format "@strong{%s} " org-closed-string) - (format (plist-get info :texinfo-inactive-timestamp-format) - (org-timestamp-translate closed))))) - (let ((deadline (org-element-property :deadline planning))) - (when deadline - (concat - (format "@strong{%s} " org-deadline-string) - (format (plist-get info :texinfo-active-timestamp-format) - (org-timestamp-translate deadline))))) - (let ((scheduled (org-element-property :scheduled planning))) - (when scheduled - (concat - (format "@strong{%s} " org-scheduled-string) - (format (plist-get info :texinfo-active-timestamp-format) - (org-timestamp-translate scheduled))))))) - " ") - "@*")) - -;;;; Property Drawer - -(defun org-texinfo-property-drawer (_property-drawer contents _info) - "Transcode a PROPERTY-DRAWER element from Org to Texinfo. -CONTENTS holds the contents of the drawer. INFO is a plist -holding contextual information." - (and (org-string-nw-p contents) - (format "@verbatim\n%s@end verbatim" contents))) - -;;;; Quote Block - -(defun org-texinfo-quote-block (quote-block contents _info) - "Transcode a QUOTE-BLOCK element from Org to Texinfo. -CONTENTS holds the contents of the block. INFO is a plist -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) "")))) - -;;;; Radio Target - -(defun org-texinfo-radio-target (radio-target text info) - "Transcode a RADIO-TARGET object from Org to Texinfo. -TEXT is the text of the target. INFO is a plist holding -contextual information." - (format "@anchor{%s}%s" - (org-texinfo--get-node radio-target info) - text)) - -;;;; Section - -(defun org-texinfo-section (section contents info) - "Transcode a SECTION element from Org to Texinfo. -CONTENTS holds the contents of the section. INFO is a plist -holding contextual information." - (let ((parent (org-export-get-parent-headline section))) - (when parent ;first section is handled in `org-texinfo-template' - (org-trim - (concat contents - "\n" - (and (not (org-export-excluded-from-toc-p parent info)) - (org-texinfo-make-menu parent info))))))) - -;;;; Special Block - -(defun org-texinfo-special-block (special-block contents _info) - "Transcode a SPECIAL-BLOCK element from Org to Texinfo. -CONTENTS holds the contents of the block. INFO is a plist used -as a communication channel." - (let ((opt (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))) - -;;;; Src Block - -(defun org-texinfo-src-block (src-block _contents info) - "Transcode a SRC-BLOCK element from Org to Texinfo. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((lisp (string-match-p "lisp" - (org-element-property :language src-block))) - (code (org-texinfo--sanitize-content - (org-export-format-code-default src-block info))) - (value (format - (if lisp "@lisp\n%s@end lisp" "@example\n%s@end example") - code)) - (caption (org-export-get-caption src-block)) - (shortcaption (org-export-get-caption src-block t))) - (if (not (or caption shortcaption)) value - (org-texinfo--wrap-float value - info - (org-export-translate "Listing" :utf-8 info) - (org-texinfo--get-node src-block info) - caption - shortcaption)))) - -;;;; Statistics Cookie - -(defun org-texinfo-statistics-cookie (statistics-cookie _contents _info) - "Transcode a STATISTICS-COOKIE object from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-element-property :value statistics-cookie)) - - -;;;; Strike-through - -(defun org-texinfo-strike-through (_strike-through contents info) - "Transcode STRIKE-THROUGH from Org to Texinfo. -CONTENTS is the text with strike-through markup. INFO is a plist -holding contextual information." - (org-texinfo--text-markup contents 'strike-through info)) - -;;;; Subscript - -(defun org-texinfo-subscript (_subscript contents _info) - "Transcode a SUBSCRIPT object from Org to Texinfo. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (format "@math{_%s}" contents)) - -;;;; Superscript - -(defun org-texinfo-superscript (_superscript contents _info) - "Transcode a SUPERSCRIPT object from Org to Texinfo. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (format "@math{^%s}" contents)) - -;;;; Table - -(defun org-texinfo-table (table contents info) - "Transcode a TABLE element from Org to Texinfo. -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))) - (let* ((col-width (org-export-read-attribute :attr_texinfo table :columns)) - (columns - (if col-width (format "@columnfractions %s" col-width) - (org-texinfo-table-column-widths table info))) - (caption (org-export-get-caption table)) - (shortcaption (org-export-get-caption table t)) - (table-str (format "@multitable %s\n%s@end multitable" - columns - contents))) - (if (not (or caption shortcaption)) table-str - (org-texinfo--wrap-float table-str - info - (org-export-translate "Table" :utf-8 info) - (org-texinfo--get-node table info) - caption - shortcaption))))) - -(defun org-texinfo-table-column-widths (table info) - "Determine the largest table cell in each column to process alignment. -TABLE is the table element to transcode. INFO is a plist used as -a communication channel." - (let ((widths (make-vector (cdr (org-export-table-dimensions table info)) 0))) - (org-element-map table 'table-row - (lambda (row) - (let ((idx 0)) - (org-element-map row 'table-cell - (lambda (cell) - ;; Length of the cell in the original buffer is only an - ;; approximation of the length of the cell in the - ;; output. It can sometimes fail (e.g. it considers - ;; "/a/" being larger than "ab"). - (let ((w (- (org-element-property :contents-end cell) - (org-element-property :contents-begin cell)))) - (aset widths idx (max w (aref widths idx)))) - (cl-incf idx)) - info))) - info) - (format "{%s}" (mapconcat (lambda (w) (make-string w ?a)) widths "} {")))) - -;;;; Table Cell - -(defun org-texinfo-table-cell (table-cell contents info) - "Transcode a TABLE-CELL element from Org to Texinfo. -CONTENTS is the cell contents. INFO is a plist used as -a communication channel." - (concat - (let ((scientific-notation - (plist-get info :texinfo-table-scientific-notation))) - (if (and contents - scientific-notation - (string-match orgtbl-exp-regexp contents)) - ;; Use appropriate format string for scientific notation. - (format scientific-notation - (match-string 1 contents) - (match-string 2 contents)) - contents)) - (when (org-export-get-next-element table-cell info) "\n@tab "))) - -;;;; Table Row - -(defun org-texinfo-table-row (table-row contents info) - "Transcode a TABLE-ROW element from Org to Texinfo. -CONTENTS is the contents of the row. INFO is a plist used as -a communication channel." - ;; Rules are ignored since table separators are deduced from - ;; borders of the current row. - (when (eq (org-element-property :type table-row) 'standard) - (let ((rowgroup-tag - (if (and (= 1 (org-export-table-row-group table-row info)) - (org-export-table-has-header-p - (org-export-get-parent-table table-row) info)) - "@headitem " - "@item "))) - (concat rowgroup-tag contents "\n")))) - -;;;; Target - -(defun org-texinfo-target (target _contents info) - "Transcode a TARGET object from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - (format "@anchor{%s}" (org-texinfo--get-node target info))) - -;;;; Timestamp - -(defun org-texinfo-timestamp (timestamp _contents info) - "Transcode a TIMESTAMP object from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - (let ((value (org-texinfo-plain-text - (org-timestamp-translate timestamp) info))) - (pcase (org-element-property :type timestamp) - ((or `active `active-range) - (format (plist-get info :texinfo-active-timestamp-format) value)) - ((or `inactive `inactive-range) - (format (plist-get info :texinfo-inactive-timestamp-format) value)) - (_ (format (plist-get info :texinfo-diary-timestamp-format) value))))) - -;;;; Underline - -(defun org-texinfo-underline (_underline contents info) - "Transcode UNDERLINE from Org to Texinfo. -CONTENTS is the text with underline markup. INFO is a plist -holding contextual information." - (org-texinfo--text-markup contents 'underline info)) - -;;;; Verbatim - -(defun org-texinfo-verbatim (verbatim _contents info) - "Transcode a VERBATIM object from Org to Texinfo. -CONTENTS is nil. INFO is a plist used as a communication -channel." - (org-texinfo--text-markup - (org-element-property :value verbatim) 'verbatim info)) - -;;;; Verse Block - -(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)) - - -;;; Interactive functions - -;;;###autoload -(defun org-texinfo-export-to-texinfo - (&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 -narrowed part. - -If a region is active, export that region. - -A non-nil optional argument ASYNC means the process should happen -asynchronously. The resulting file should be accessible through -the `org-export-stack' interface. - -When optional argument SUBTREEP is non-nil, export the sub-tree -at point, extracting information from the headline properties -first. - -When optional argument VISIBLE-ONLY is non-nil, don't export -contents of hidden elements. - -When optional argument BODY-ONLY is non-nil, only write code -between \"\\begin{document}\" and \"\\end{document}\". - -EXT-PLIST, when provided, is a property list with external -parameters overriding Org default settings, but still inferior to -file-local settings. - -Return output file's name." - (interactive) - (let ((outfile (org-export-output-file-name ".texi" subtreep)) - (org-export-coding-system org-texinfo-coding-system)) - (org-export-to-file 'texinfo outfile - async subtreep visible-only body-only ext-plist))) - -(defun org-texinfo-export-to-texinfo-batch () - "Export Org file INFILE to Texinfo file OUTFILE, in batch mode. -Overwrites existing output file. -Usage: emacs -batch -f org-texinfo-export-to-texinfo-batch INFILE OUTFILE" - (or noninteractive (user-error "Batch mode use only")) - (let ((infile (pop command-line-args-left)) - (outfile (pop command-line-args-left)) - (org-export-coding-system org-texinfo-coding-system) - (make-backup-files nil)) - (unless (file-readable-p infile) - (message "File `%s' not readable" infile) - (kill-emacs 1)) - (with-temp-buffer - (insert-file-contents infile) - (org-export-to-file 'texinfo outfile)))) - -;;;###autoload -(defun org-texinfo-export-to-info - (&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 -narrowed part. - -If a region is active, export that region. - -A non-nil optional argument ASYNC means the process should happen -asynchronously. The resulting file should be accessible through -the `org-export-stack' interface. - -When optional argument SUBTREEP is non-nil, export the sub-tree -at point, extracting information from the headline properties -first. - -When optional argument VISIBLE-ONLY is non-nil, don't export -contents of hidden elements. - -When optional argument BODY-ONLY is non-nil, only write code -between \"\\begin{document}\" and \"\\end{document}\". - -EXT-PLIST, when provided, is a property list with external -parameters overriding Org default settings, but still inferior to -file-local settings. - -When optional argument PUB-DIR is set, use it as the publishing -directory. - -Return INFO file's name." - (interactive) - (let ((outfile (org-export-output-file-name ".texi" subtreep)) - (org-export-coding-system org-texinfo-coding-system)) - (org-export-to-file 'texinfo outfile - async subtreep visible-only body-only ext-plist - #'org-texinfo-compile))) - -;;;###autoload -(defun org-texinfo-publish-to-texinfo (plist filename pub-dir) - "Publish an org file to Texinfo. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-publish-org-to 'texinfo filename ".texi" plist pub-dir)) - -;;;###autoload -(defun org-texinfo-convert-region-to-texinfo () - "Assume the current region has Org syntax, and convert it to Texinfo. -This can be used in any buffer. For example, you can write an -itemized list in Org syntax in an Texinfo buffer and use this -command to convert it." - (interactive) - (org-export-replace-region-by 'texinfo)) - -(defun org-texinfo-compile (file) - "Compile a texinfo file. - -FILE is the name of the file being compiled. Processing is done -through the command specified in `org-texinfo-info-process', -which see. Output is redirected to \"*Org INFO Texinfo Output*\" -buffer. - -Return INFO file name or an error if it couldn't be produced." - (message "Processing Texinfo file %s..." file) - (let* ((log-name "*Org INFO Texinfo Output*") - (log (get-buffer-create log-name)) - (output - (org-compile-file file org-texinfo-info-process "info" - (format "See %S for details" log-name) - log))) - (when org-texinfo-remove-logfiles - (let ((base (file-name-sans-extension output))) - (dolist (ext org-texinfo-logfiles-extensions) - (let ((file (concat base "." ext))) - (when (file-exists-p file) (delete-file file)))))) - (message "Process completed.") - output)) - - -(provide 'ox-texinfo) - -;; Local variables: -;; generated-autoload-file: "org-loaddefs.el" -;; End: - -;;; ox-texinfo.el ends here |