diff options
author | Sébastien Delafond <sdelafond@gmail.com> | 2014-07-13 13:35:27 +0200 |
---|---|---|
committer | Sébastien Delafond <sdelafond@gmail.com> | 2014-07-13 13:35:27 +0200 |
commit | e32a45ed36d6000db4b39171149072d11b77af72 (patch) | |
tree | b5f4a7d43022c08c3298e82b3e9fc50f68be660f /contrib/lisp/org-e-texinfo.el | |
parent | 7697fa4daf3ec84f85711a84035d8f0224afd4e3 (diff) |
Imported Upstream version 8.0.7
Diffstat (limited to 'contrib/lisp/org-e-texinfo.el')
-rw-r--r-- | contrib/lisp/org-e-texinfo.el | 1844 |
1 files changed, 0 insertions, 1844 deletions
diff --git a/contrib/lisp/org-e-texinfo.el b/contrib/lisp/org-e-texinfo.el deleted file mode 100644 index a19139f..0000000 --- a/contrib/lisp/org-e-texinfo.el +++ /dev/null @@ -1,1844 +0,0 @@ -;;; org-e-texinfo.el --- Texinfo Back-End For Org Export Engine - -;; Copyright (C) 2012 Jonathan Leech-Pepin -;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com> -;; Keywords: outlines, hypermedia, calendar, wp -;; -;; This file is not part of GNU Emacs. -;; -;; This program 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. - -;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; -;; This library implements a Texinfo back-end for Org generic -;; exporter. -;; -;; To test it, run -;; -;; M-: (org-export-to-buffer 'e-texinfo "*Test e-texinfo*") RET -;; -;; in an org-mode buffer then switch to the buffer to see the Texinfo -;; export. See contrib/lisp/org-export.el for more details on how -;; this exporter works. -;; -;; It introduces eight new buffer keywords: "TEXINFO_CLASS", -;; "TEXINFO_FILENAME", "TEXINFO_HEADER", "TEXINFO_DIR_CATEGORY", -;; "TEXINFO_DIR_TITLE", "TEXINFO_DIR_DESC" "SUBTITLE" and "SUBAUTHOR". -;; -;; To include inline code snippets (for example for generating @kbd{} -;; and @key{} commands), the following export-snippet keys are -;; accepted: -;; -;; info -;; e-info -;; e-texinfo -;; -;; You can add them for export snippets via any of the below: -;; -;; (add-to-list 'org-export-snippet-translation-alist -;; '("e-info" . "e-texinfo")) -;; (add-to-list 'org-export-snippet-translation-alist -;; '("e-texinfo" . "e-texinfo")) -;; (add-to-list 'org-export-snippet-translation-alist -;; '("info" . "e-texinfo")) -;; - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'org-export) - -(defvar orgtbl-exp-regexp) - - -;;; Define Back-End - -(defvar org-e-texinfo-translate-alist - '((babel-call . org-e-texinfo-babel-call) - (bold . org-e-texinfo-bold) - (center-block . org-e-texinfo-center-block) - (clock . org-e-texinfo-clock) - (code . org-e-texinfo-code) - (comment . org-e-texinfo-comment) - (comment-block . org-e-texinfo-comment-block) - (drawer . org-e-texinfo-drawer) - (dynamic-block . org-e-texinfo-dynamic-block) - (entity . org-e-texinfo-entity) - (example-block . org-e-texinfo-example-block) - (export-block . org-e-texinfo-export-block) - (export-snippet . org-e-texinfo-export-snippet) - (fixed-width . org-e-texinfo-fixed-width) - (footnote-definition . org-e-texinfo-footnote-definition) - (footnote-reference . org-e-texinfo-footnote-reference) - (headline . org-e-texinfo-headline) - (horizontal-rule . org-e-texinfo-horizontal-rule) - (inline-babel-call . org-e-texinfo-inline-babel-call) - (inline-src-block . org-e-texinfo-inline-src-block) - (inlinetask . org-e-texinfo-inlinetask) - (italic . org-e-texinfo-italic) - (item . org-e-texinfo-item) - (keyword . org-e-texinfo-keyword) - (latex-environment . org-e-texinfo-latex-environment) - (latex-fragment . org-e-texinfo-latex-fragment) - (line-break . org-e-texinfo-line-break) - (link . org-e-texinfo-link) - (macro . org-e-texinfo-macro) - (paragraph . org-e-texinfo-paragraph) - (plain-list . org-e-texinfo-plain-list) - (plain-text . org-e-texinfo-plain-text) - (planning . org-e-texinfo-planning) - (property-drawer . org-e-texinfo-property-drawer) - (quote-block . org-e-texinfo-quote-block) - (quote-section . org-e-texinfo-quote-section) - (radio-target . org-e-texinfo-radio-target) - (section . org-e-texinfo-section) - (special-block . org-e-texinfo-special-block) - (src-block . org-e-texinfo-src-block) - (statistics-cookie . org-e-texinfo-statistics-cookie) - (strike-through . org-e-texinfo-strike-through) - (subscript . org-e-texinfo-subscript) - (superscript . org-e-texinfo-superscript) - (table . org-e-texinfo-table) - (table-cell . org-e-texinfo-table-cell) - (table-row . org-e-texinfo-table-row) - (target . org-e-texinfo-target) - (template . org-e-texinfo-template) - (timestamp . org-e-texinfo-timestamp) - (underline . org-e-texinfo-underline) - (verbatim . org-e-texinfo-verbatim) - (verse-block . org-e-texinfo-verse-block)) - "Alist between element or object types and translators.") - -(defconst org-e-texinfo-options-alist - '((:texinfo-filename "TEXINFO_FILENAME" nil org-e-texinfo-filename t) - (:texinfo-class "TEXINFO_CLASS" nil org-e-texinfo-default-class t) - (:texinfo-header "TEXINFO_HEADER" nil nil newline) - (:subtitle "SUBTITLE" nil nil newline) - (: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)) - "Alist between Texinfo export properties and ways to set them. -See `org-export-options-alist' for more information on the -structure of the values. - -SUBAUTHOR and SUBTITLE are for the inclusion of additional author -and title information beyond the initial variable.") - -(defconst org-e-texinfo-filters-alist - '((:filter-headline . org-e-texinfo-filter-section-blank-lines) - (:filter-section . org-e-texinfo-filter-section-blank-lines)) - "Alist between filters keywords and back-end specific filters. - See `org-export-filters-alist' for more information") - - -;;; Internal Variables - -;; Add TEXINFO to the list of available of available export blocks. -(add-to-list 'org-element-block-name-alist - '("TEXINFO" . org-element-export-block-parser)) - -;;; User Configurable Variables - -(defgroup org-export-e-texinfo nil - "Options for exporting Org mode files to Texinfo." - :tag "Org Export Texinfo" - :group 'org-export) - -;;; Preamble - -(defcustom org-e-texinfo-filename nil - "Default filename for texinfo output." - :group 'org-export-e-texinfo - :type '(string :tag "Export Filename")) - -(defcustom org-e-texinfo-default-class "info" - "The default Texinfo class." - :group 'org-export-e-texinfo - :type '(string :tag "Texinfo class")) - -(defcustom org-e-texinfo-classes - '(("info" - "\\input texinfo @c -*- texinfo -*-" - ("@chapter %s" . "@unnumbered %s") - ("@section %s" . "@unnumberedsec %s") - ("@subsection %s" . "@unnumberedsubsec %s") - ("@subsubsection %s" . "@unnumberedsubsubsec %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 each cell: - - \(class-name - header-string - \(numbered-section . unnumbered-section\) - ...\) - -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. - -Instead of a list of sectioning commands, you can also specify -a function name. That function will be called with two -parameters, the \(reduced) level of the headline, and a predicate -non-nil when the headline should be numbered. It must return -a format string in which the section title will be added." - :group 'org-export-e-texinfo - :type '(repeat - (list (string :tag "Texinfo class") - (string :tag "Texinfo header") - (repeat :tag "Levels" :inline t - (choice - (cons :tag "Heading" - (string :tag " numbered") - (string :tag "unnumbered")) - (function :tag "Hook computing sectioning")))))) - -;;; Headline - -(defcustom org-e-texinfo-format-headline-function nil - "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. - -As an example, one could set the variable to the following, in -order to reproduce the default set-up: - -\(defun org-e-texinfo-format-headline (todo todo-type priority text tags) - \"Default format function for an headline.\" - \(concat (when todo - \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo)) - \(when priority - \(format \"\\\\framebox{\\\\#%c} \" priority)) - text - \(when tags - \(format \"\\\\hfill{}\\\\textsc{%s}\" - \(mapconcat 'identity tags \":\"))))" - :group 'org-export-e-texinfo - :type 'function) - - -;;; Footnotes -;; -;; Footnotes are inserted directly - -;;; Timestamps - -(defcustom org-e-texinfo-active-timestamp-format "@emph{%s}" - "A printf format string to be applied to active timestamps." - :group 'org-export-e-texinfo - :type 'string) - -(defcustom org-e-texinfo-inactive-timestamp-format "@emph{%s}" - "A printf format string to be applied to inactive timestamps." - :group 'org-export-e-texinfo - :type 'string) - -(defcustom org-e-texinfo-diary-timestamp-format "@emph{%s}" - "A printf format string to be applied to diary timestamps." - :group 'org-export-e-texinfo - :type 'string) - -;;; Links - -(defcustom org-e-texinfo-link-with-unknown-path-format "@indicateurl{%s}" - "Format string for links with unknown path type." - :group 'org-export-e-texinfo - :type 'string) - -;;; Tables - -(defcustom org-e-texinfo-tables-verbatim nil - "When non-nil, tables are exported verbatim." - :group 'org-export-e-texinfo - :type 'boolean) - -(defcustom org-e-texinfo-table-scientific-notation "%s\\,(%s)" - "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-e-texinfo - :type '(choice - (string :tag "Format string") - (const :tag "No formatting"))) - -(defcustom org-e-texinfo-def-table-markup "@samp" - "Default setting for @table environments.") - -;;; Text markup - -(defcustom org-e-texinfo-text-markup-alist '((bold . "@strong{%s}") - (code . code) - (italic . "@emph{%s}") - (verbatim . verb) - (comment . "@c %s")) - "Alist of Texinfo expressions to convert text markup. - -The key must be a symbol among `bold', `italic' and `comment'. -The value is a formatting string to wrap fontified text with. - -Value can also be set to the following symbols: `verb' and -`code'. For the former, Org will use \"@verb\" to -create a format string and select a delimiter character that -isn't in the string. For the latter, Org will use \"@code\" -to typeset and try to protect special characters. - -If no association can be found for a given markup, text will be -returned as-is." - :group 'org-export-e-texinfo - :type 'alist - :options '(bold code italic verbatim comment)) - -;;; Drawers - -(defcustom org-e-texinfo-format-drawer-function nil - "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. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-texinfo-format-drawer-default \(name contents\) - \"Format a drawer element for Texinfo export.\" - contents\)" - :group 'org-export-e-texinfo - :type 'function) - -;;; Inlinetasks - -(defcustom org-e-texinfo-format-inlinetask-function nil - "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. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-texinfo-format-inlinetask \(todo type priority name tags contents\) -\"Format an inline task element for Texinfo export.\" - \(let ((full-title - \(concat - \(when todo - \(format \"@strong{%s} \" todo)) - \(when priority (format \"#%c \" priority)) - title - \(when tags - \(format \":%s:\" - \(mapconcat 'identity tags \":\"))))) - \(format (concat \"@center %s\n\n\" - \"%s\" - \"\n\")) - full-title contents))" - :group 'org-export-e-texinfo - :type 'function) - -;;; Src blocks -;; -;; Src Blocks are example blocks, except for LISP - -;;; Plain text - -(defcustom org-e-texinfo-quotes - '(("quotes" - ("\\(\\s-\\|[[(]\\|^\\)\"" . "``") - ("\\(\\S-\\)\"" . "''") - ("\\(\\s-\\|(\\|^\\)'" . "`"))) - "Alist for quotes to use when converting english double-quotes. - -The CAR of each item in this alist is the language code. -The CDR of each item in this alist is a list of three CONS: -- the first CONS defines the opening quote; -- the second CONS defines the closing quote; -- the last CONS defines single quotes. - -For each item in a CONS, the first string is a regexp -for allowed characters before/after the quote, the second -string defines the replacement string for this quote." - :group 'org-export-e-texinfo - :type '(list - (cons :tag "Opening quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")) - (cons :tag "Closing quote" - (string :tag "Regexp for char after ") - (string :tag "Replacement quote ")) - (cons :tag "Single quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")))) - -;;; Compilation - -(defcustom org-e-texinfo-info-process - '("makeinfo %f") - "Commands to process a texinfo file to an INFO file. -This is list of strings, each of them will be given to the shell -as a command. %f in the command will be replaced by the full -file name, %b by the file base name \(i.e without extension) and -%o by the base directory of the file." - :group 'org-export-texinfo - :type '(repeat :tag "Shell command sequence" - (string :tag "Shell command"))) - - -;;; Internal Functions - -(defun org-e-texinfo-filter-section-blank-lines (headline back-end info) - "Filter controlling number of blank lines after a section." - (let ((blanks (make-string 2 ?\n))) - (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline))) - -(defun org-e-texinfo--find-copying (info) - "Retrieve the headline identified by the property :copying:. - -INFO is the plist containing the export options and tree. It is -used to find and extract the single desired headline. This -cannot be treated as a standard headline since it must be -inserted in a specific location." - (let (copying) - (org-element-map (plist-get info :parse-tree) 'headline - (lambda (copy) - (when (org-element-property :copying copy) - (push copy copying))) info 't) - ;; Retrieve the single entry - (car copying))) - -(defun org-e-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<>()[]{}")) - (loop for c across ll - when (not (string-match (regexp-quote (char-to-string c)) s)) - return (char-to-string c)))) - -(defun org-e-texinfo--make-option-string (options) - "Return a comma separated string of keywords and values. -OPTIONS is an alist where the key is the options keyword as -a string, and the value a list containing the keyword value, or -nil." - (mapconcat (lambda (pair) - (concat (first pair) - (when (> (length (second pair)) 0) - (concat "=" (second pair))))) - options - ",")) - -(defun org-e-texinfo--quotation-marks (text info) - "Export quotation marks using ` and ' as the markers. -TEXT is a string containing quotation marks to be replaced. INFO -is a plist used as a communication channel." - (mapc (lambda(l) - (let ((start 0)) - (while (setq start (string-match (car l) text start)) - (let ((new-quote (concat (match-string 1 text) (cdr l)))) - (setq text (replace-match new-quote t t text)))))) - (cdr org-e-texinfo-quotes)) - text) - -(defun org-e-texinfo--text-markup (text markup) - "Format TEXT depending on MARKUP text markup. -See `org-e-texinfo-text-markup-alist' for details." - (let ((fmt (cdr (assq markup org-e-texinfo-text-markup-alist)))) - (cond - ;; No format string: Return raw text. - ((not fmt) text) - ((eq 'verb fmt) - (let ((separator (org-e-texinfo--find-verb-separator text))) - (concat "@verb{" separator text separator "}"))) - ((eq 'code fmt) - (let ((start 0) - (rtn "") - char) - (while (string-match "[@{}]" text) - (setq char (match-string 0 text)) - (if (> (match-beginning 0) 0) - (setq rtn (concat rtn (substring text 0 (match-beginning 0))))) - (setq text (substring text (1+ (match-beginning 0)))) - (setq char (concat "@" char) - rtn (concat rtn char))) - (setq text (concat rtn text) - fmt "@code{%s}") - (format fmt text))) - ;; Else use format string. - (t (format fmt text))))) - -;;; Headline sanitizing - -(defun org-e-texinfo--sanitize-headline (headline info) - "Remove all formatting from the text of a headline for use in - node and menu listing." - (mapconcat 'identity - (org-e-texinfo--sanitize-headline-contents headline info) " ")) - -(defun org-e-texinfo--sanitize-headline-contents (headline info) - "Retrieve the content of the headline. - -Any content that can contain further formatting is checked -recursively, to ensure that nested content is also properly -retrieved." - (loop for contents in headline append - (cond - ;; already a string - ((stringp contents) - (list (replace-regexp-in-string " $" "" contents))) - ;; Is exported as-is (value) - ((org-element-map contents '(verbatim code) - (lambda (value) - (org-element-property :value value)))) - ;; Has content and recurse into the content - ((org-element-contents contents) - (org-e-texinfo--sanitize-headline-contents - (org-element-contents contents) info))))) - -;;; Menu sanitizing - -(defun org-e-texinfo--sanitize-menu (title) - "Remove invalid characters from TITLE for use in menus and -nodes. - -Based on TEXINFO specifications, the following must be removed: -@ { } ( ) : . ," - (replace-regexp-in-string "[@{}():,.]" "" title)) - -;;; Content sanitizing - -(defun org-e-texinfo--sanitize-content (text) - "Ensure characters are properly escaped when used in headlines or blocks. - -Escape characters are: @ { }" - (replace-regexp-in-string "\\\([@{}]\\\)" "@\\1" text)) - -;;; Menu creation - -(defun org-e-texinfo--build-menu (tree level info &optional detailed) - "Create the @menu/@end menu information from TREE at headline -level LEVEL. - -TREE contains the parse-tree to work with, either of the entire -document or of a specific parent headline. LEVEL indicates what -level of headlines to look at when generating the menu. INFO is -a plist containing contextual information. - -Detailed determines whether to build a single level of menu, or -recurse into all children as well." - (let ((menu (org-e-texinfo--generate-menu-list tree level info)) - output text-menu) - (cond - (detailed - ;; Looping is done within the menu generation. - (setq text-menu (org-e-texinfo--generate-detailed menu level info))) - (t - (setq text-menu (org-e-texinfo--generate-menu-items menu info)))) - (when text-menu - (setq output (org-e-texinfo--format-menu text-menu)) - (mapconcat 'identity output "\n")))) - -(defun org-e-texinfo--generate-detailed (menu level info) - "Generate a detailed listing of all subheadings within MENU starting at LEVEL. - -MENU is the parse-tree to work with. LEVEL is the starting level -for the menu headlines and from which recursion occurs. INFO is -a plist containing contextual information." - (when level - (let ((max-depth (plist-get info :headline-levels))) - (when (> max-depth level) - (loop for headline in menu append - (let* ((title (org-e-texinfo--menu-headlines headline info)) - ;; Create list of menu entries for the next level - (sublist (org-e-texinfo--generate-menu-list - headline (1+ level) info)) - ;; Generate the menu items for that level. If - ;; there are none omit that heading completely, - ;; otherwise join the title to it's related entries. - (submenu (if (org-e-texinfo--generate-menu-items sublist info) - (append (list title) - (org-e-texinfo--generate-menu-items sublist info)) - 'nil)) - ;; Start the process over the next level down. - (recursion (org-e-texinfo--generate-detailed sublist (1+ level) info))) - (setq recursion (append submenu recursion)) - recursion)))))) - -(defun org-e-texinfo--generate-menu-list (tree level info) - "Generate the list of headlines that are within a given level -of the tree for further formatting. - -TREE is the parse-tree containing the headlines. LEVEL is the -headline level to generate a list of. INFO is a plist holding -contextual information." - (let (seq) - (org-element-map - tree 'headline - (lambda (head) - (when (org-element-property :level head) - (if (and (eq level (org-element-property :level head)) - ;; Do not take note of footnotes or copying headlines - (not (org-element-property :copying head)) - (not (org-element-property :footnote-section-p head))) - (push head seq))))) - ;; Return the list of headlines (reverse to have in actual order) - (reverse seq))) - -(defun org-e-texinfo--generate-menu-items (items info) - "Generate a list of headline information from the listing ITEMS. - -ITEMS is a list of the headlines to be converted into entries. -INFO is a plist containing contextual information. - -Returns a list containing the following information from each -headline: length, title, description. This is used to format the -menu using `org-e-texinfo--format-menu'." - (loop for headline in items collect - (let* ((title (org-e-texinfo--sanitize-menu - (org-e-texinfo--sanitize-headline - (org-element-property :title headline) info))) - (descr (org-export-data - (org-element-property :description headline) info)) - (len (length title)) - (output (list len title descr))) - output))) - -(defun org-e-texinfo--menu-headlines (headline info) - "Retrieve the title from HEADLINE. - -INFO is a plist holding contextual information. - -Return the headline as a list of (length title description) with -length of -1 and nil description. This is used in -`org-e-texinfo--format-menu' to identify headlines as opposed to -entries." - (let ((title (org-export-data - (org-element-property :title headline) info))) - (list -1 title 'nil))) - -(defun org-e-texinfo--format-menu (text-menu) - "Format the TEXT-MENU items to be properly printed in the menu. - -Each entry in the menu should be provided as (length title -description). - -Headlines in the detailed menu are given length -1 to ensure they -are never confused with other entries. They also have no -description. - -Other menu items are output as: - Title:: description - -With the spacing between :: and description based on the length -of the longest menu entry." - - (let* ((lengths (mapcar 'car text-menu)) - (max-length (apply 'max lengths)) - output) - (setq output - (mapcar (lambda (name) - (let* ((title (nth 1 name)) - (desc (nth 2 name)) - (length (nth 0 name))) - (if (> length -1) - (concat "* " title ":: " - (make-string - (- (+ 3 max-length) length) - ?\s) - (if desc - (concat desc))) - (concat "\n" title "\n")))) - text-menu)) - output)) - -;;; Template - -(defun org-e-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)) - (info-filename (or (plist-get info :texinfo-filename) - (file-name-nondirectory - (org-export-output-file-name ".info")))) - (author (org-export-data (plist-get info :author) info)) - (texinfo-header (plist-get info :texinfo-header)) - (subtitle (plist-get info :subtitle)) - (subauthor (plist-get info :subauthor)) - (class (plist-get info :texinfo-class)) - (header (nth 1 (assoc class org-e-texinfo-classes))) - (copying (org-e-texinfo--find-copying info)) - (dircat (plist-get info :texinfo-dircat)) - (dirtitle (plist-get info :texinfo-dirtitle)) - (dirdesc (plist-get info :texinfo-dirdesc)) - ;; Spacing to align description (column 32 - 3 for `* ' and - ;; `.' in text. - (dirspacing (- 29 (length dirtitle))) - (menu (org-e-texinfo-make-menu info 'main)) - (detail-menu (org-e-texinfo-make-menu info 'detailed))) - (concat - ;; Header - header "\n" - "@c %**start of header\n" - ;; Filename and Title - "@setfilename " info-filename "\n" - "@settitle " title "\n" - "\n\n" - "@c Version and Contact Info\n" - "@set AUTHOR " author "\n" - - ;; Additional Header Options set by `#+TEXINFO_HEADER - (if texinfo-header - (concat "\n" - texinfo-header - "\n")) - - "@c %**end of header\n" - "@finalout\n" - "\n\n" - - ;; Copying - "@copying\n" - ;; Only export the content of the headline, do not need the - ;; initial headline. - (org-export-data (nth 2 copying) info) - "@end copying\n" - "\n\n" - - ;; Info directory information - ;; Only supply if both title and category are provided - (if (and dircat dirtitle) - (concat "@dircategory " dircat "\n" - "@direntry\n" - "* " dirtitle "." - (make-string dirspacing ?\s) - dirdesc "\n" - "@end direntry\n")) - "\n\n" - - ;; Title - "@titlepage\n" - "@title " title "\n\n" - (if subtitle - (concat "@subtitle " subtitle "\n")) - "@author " author "\n" - (if subauthor - (concat subauthor "\n")) - "\n" - "@c The following two commands start the copyright page.\n" - "@page\n" - "@vskip 0pt plus 1filll\n" - "@insertcopying\n" - "@end titlepage\n\n" - "@c Output the table of contents at the beginning.\n" - "@contents\n\n" - - ;; Configure Top Node when not for Tex - "@ifnottex\n" - "@node Top\n" - "@top " title " Manual\n" - "@insertcopying\n" - "@end ifnottex\n\n" - - ;; Do not output menus if they are empty - (if menu - ;; Menu - (concat "@menu\n" - menu - "\n\n" - ;; Detailed Menu - (if detail-menu - (concat "@detailmenu\n" - " --- The Detailed Node Listing ---\n" - detail-menu - "\n\n" - "@end detailmenu\n")) - "@end menu\n")) - "\n\n" - - ;; Document's body. - contents - "\n" - ;; Creator. - (let ((creator-info (plist-get info :with-creator))) - (cond - ((not creator-info) "") - ((eq creator-info 'comment) - (format "@c %s\n" (plist-get info :creator))) - (t (concat (plist-get info :creator) "\n")))) - ;; Document end. - "\n@bye"))) - - - -;;; Transcode Functions - -;;; Babel Call -;; -;; Babel Calls are ignored. - -;;; Bold - -(defun org-e-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-e-texinfo--text-markup contents 'bold)) - -;;; Center Block -;; -;; Center blocks are ignored - -;;; Clock - -(defun org-e-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 org-e-texinfo-inactive-timestamp-format - (concat (org-translate-time (org-element-property :value clock)) - (let ((time (org-element-property :time clock))) - (and time (format " (%s)" time))))) - "@*")) - -;;; Code - -(defun org-e-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-e-texinfo--text-markup (org-element-property :value code) 'code)) - -;;; Comment - -(defun org-e-texinfo-comment (comment contents info) - "Transcode a COMMENT object from Org to Texinfo. -CONTENTS is the text in the comment. INFO is a plist holding -contextual information." - (org-e-texinfo--text-markup (org-element-property :value comment) 'comment)) - -;;; Comment Block - -(defun org-e-texinfo-comment-block (comment-block contents info) - "Transcode a COMMENT-BLOCK object from Org to Texinfo. -CONTENTS is the text within the block. INFO is a plist holding -contextual information." - (format "@ignore\n%s@end ignore" (org-element-property :value comment-block))) - -;;; Drawer - -(defun org-e-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 (if (functionp org-e-texinfo-format-drawer-function) - (funcall org-e-texinfo-format-drawer-function - name contents) - ;; If there's no user defined function: simply - ;; display contents of the drawer. - contents))) - output)) - -;;; Dynamic Block - -(defun org-e-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. See `org-export-data'." - contents) - -;;; Entity - -(defun org-e-texinfo-entity (entity contents info) - "Transcode an ENTITY object from Org to Texinfo. -CONTENTS are the definition itself. INFO is a plist holding -contextual information." - (let ((ent (org-element-property :latex entity))) - (if (org-element-property :latex-math-p entity) (format "@math{%s}" ent) ent))) - -;;; Example Block - -(defun org-e-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 "@verbatim\n%s@end verbatim" - (org-export-format-code-default example-block info))) - -;;; Export Block - -(defun org-e-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-e-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) 'e-texinfo) - (org-element-property :value export-snippet))) - -;;; Fixed Width - -(defun org-e-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-e-texinfo--sanitize-content - (org-element-property :value fixed-width))))) - -;;; Footnote Definition -;; -;; Footnote Definitions are ignored. - -;;; Footnote Reference -;; - -(defun org-e-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 ((def (org-export-get-footnote-definition footnote info))) - (format "@footnote{%s}" - (org-trim (org-export-data def info))))) - -;;; Headline - -(defun org-e-texinfo-headline (headline contents info) - "Transcode an HEADLINE element from Org to Texinfo. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((class (plist-get info :texinfo-class)) - (level (org-export-get-relative-level headline info)) - (numberedp (org-export-numbered-headline-p headline info)) - (class-sectionning (assoc class org-e-texinfo-classes)) - ;; Find the index type, if any - (index (org-element-property :index headline)) - ;; Retrieve headline text - (text (org-e-texinfo--sanitize-headline - (org-element-property :title headline) info)) - ;; Create node info, to insert it before section formatting. - (node (format "@node %s\n" - (org-e-texinfo--sanitize-menu - (replace-regexp-in-string "%" "%%" text)))) - ;; Menus must be generated with first child, otherwise they - ;; will not nest properly - (menu (let* ((first (org-export-first-sibling-p headline info)) - (parent (org-export-get-parent-headline headline)) - (title (org-e-texinfo--sanitize-headline - (org-element-property :title parent) info)) - heading listing - (tree (plist-get info :parse-tree))) - (if first - (org-element-map - (plist-get info :parse-tree) 'headline - (lambda (ref) - (if (member title (org-element-property :title ref)) - (push ref heading))) - info 't)) - (setq listing (org-e-texinfo--build-menu - (car heading) level info)) - (if listing - (setq listing (replace-regexp-in-string - "%" "%%" listing) - listing (format - "\n@menu\n%s\n@end menu\n\n" listing)) - 'nil))) - ;; Section formatting will set two placeholders: one for the - ;; title and the other for the contents. - (section-fmt - (let ((sec (if (and (symbolp (nth 2 class-sectionning)) - (fboundp (nth 2 class-sectionning))) - (funcall (nth 2 class-sectionning) level numberedp) - (nth (1+ level) class-sectionning)))) - (cond - ;; No section available for that LEVEL. - ((not sec) nil) - ;; Section format directly returned by a function. - ((stringp sec) sec) - ;; (numbered-section . unnumbered-section) - ((not (consp (cdr sec))) - ;; If an index, always unnumbered - (if index - (concat menu node (cdr sec) "\n%s") - ;; Otherwise number as needed. - (concat menu node - (funcall - (if numberedp #'car #'cdr) sec) "\n%s")))))) - (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))) - ;; Create the headline text along with a no-tag version. The - ;; latter is required to remove tags from table of contents. - (full-text (org-e-texinfo--sanitize-content - (if (functionp org-e-texinfo-format-headline-function) - ;; User-defined formatting function. - (funcall org-e-texinfo-format-headline-function - todo todo-type priority text tags) - ;; Default formatting. - (concat - (when todo - (format "@strong{%s} " todo)) - (when priority (format "@emph{#%s} " priority)) - text - (when tags - (format ":%s:" - (mapconcat 'identity tags ":"))))))) - (full-text-no-tag - (org-e-texinfo--sanitize-content - (if (functionp org-e-texinfo-format-headline-function) - ;; User-defined formatting function. - (funcall org-e-texinfo-format-headline-function - todo todo-type priority text nil) - ;; Default formatting. - (concat - (when todo (format "@strong{%s} " todo)) - (when priority (format "@emph{#%c} " priority)) - text)))) - (pre-blanks - (make-string (org-element-property :pre-blank headline) 10))) - (cond - ;; Case 1: This is a footnote section: ignore it. - ((org-element-property :footnote-section-p headline) nil) - ;; Case 2: This is the `copying' section: ignore it - ;; This is used elsewhere. - ((org-element-property :copying headline) nil) - ;; Case 3: An index. If it matches one of the known indexes, - ;; print it as such following the contents, otherwise - ;; print the contents and leave the index up to the user. - (index - (format - section-fmt full-text - (concat pre-blanks contents "\n" - (if (member index '("cp" "fn" "ky" "pg" "tp" "vr")) - (concat "@printindex " index))))) - ;; Case 4: This is a deep sub-tree: export it as a list item. - ;; Also export as items headlines for which no section - ;; format has been found. - ((or (not section-fmt) (org-export-low-level-p headline info)) - ;; Build the real contents of the sub-tree. - (let ((low-level-body - (concat - ;; If the headline is the first sibling, start a list. - (when (org-export-first-sibling-p headline info) - (format "@%s\n" (if numberedp 'enumerate 'itemize))) - ;; Itemize headline - "@item\n" full-text "\n" pre-blanks contents))) - ;; If headline is not the last sibling simply return - ;; LOW-LEVEL-BODY. Otherwise, also close the list, before any - ;; blank line. - (if (not (org-export-last-sibling-p headline info)) low-level-body - (replace-regexp-in-string - "[ \t\n]*\\'" - (format "\n@end %s" (if numberedp 'enumerate 'itemize)) - low-level-body)))) - ;; Case 5: Standard headline. Export it as a section. - (t - (cond - ((not (and tags (eq (plist-get info :with-tags) 'not-in-toc))) - ;; Regular section. Use specified format string. - (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text - (concat pre-blanks contents))) - ((string-match "\\`@\\(.*?\\){" section-fmt) - ;; If tags should be removed from table of contents, insert - ;; title without tags as an alternative heading in sectioning - ;; command. - (format (replace-match (concat (match-string 1 section-fmt) "[%s]") - nil nil section-fmt 1) - ;; Replace square brackets with parenthesis since - ;; square brackets are not supported in optional - ;; arguments. - (replace-regexp-in-string - "\\[" "(" - (replace-regexp-in-string - "\\]" ")" - full-text-no-tag)) - full-text - (concat pre-blanks contents))) - (t - ;; Impossible to add an alternative heading. Fallback to - ;; regular sectioning format string. - (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text - (concat pre-blanks contents)))))))) - -;;; Horizontal Rule -;; -;; Horizontal rules are ignored - -;;; Inline Babel Call -;; -;; Inline Babel Calls are ignored. - -;;; Inline Src Block - -(defun org-e-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." - (let* ((code (org-element-property :value inline-src-block)) - (separator (org-e-texinfo--find-verb-separator code))) - (concat "@verb{" separator code separator "}"))) - -;;; Inlinetask - -(defun org-e-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)))) - ;; If `org-e-texinfo-format-inlinetask-function' is provided, call it - ;; with appropriate arguments. - (if (functionp org-e-texinfo-format-inlinetask-function) - (funcall org-e-texinfo-format-inlinetask-function - todo todo-type priority title tags contents) - ;; Otherwise, use a default template. - (let ((full-title - (concat - (when todo (format "@strong{%s} " todo)) - (when priority (format "#%c " priority)) - title - (when tags (format ":%s:" - (mapconcat 'identity tags ":")))))) - (format (concat "@center %s\n\n" - "%s" - "\n") - full-title contents))))) - -;;; Italic - -(defun org-e-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-e-texinfo--text-markup contents 'italic)) - -;;; Item - -(defun org-e-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)) - (desc (org-export-data tag info))) - (concat "\n@item " (if tag desc) "\n" - (org-trim contents) "\n"))) - -;;; Keyword - -(defun org-e-texinfo-keyword (keyword contents info) - "Transcode a KEYWORD element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((key (org-element-property :key keyword)) - (value (org-element-property :value keyword))) - (cond - ((string= key "TEXINFO") value) - ((string= key "CINDEX") (format "@cindex %s" value)) - ((string= key "FINDEX") (format "@findex %s" value)) - ((string= key "KINDEX") (format "@kindex %s" value)) - ((string= key "PINDEX") (format "@pindex %s" value)) - ((string= key "TINDEX") (format "@tindex %s" value)) - ((string= key "VINDEX") (format "@vindex %s" value))))) - -;;; Latex Environment -;; -;; Latex environments are ignored - -;;; Latex Fragment -;; -;; Latex fragments are ignored. - -;;; Line Break - -(defun org-e-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." - "@*") - -;;; Link - -(defun org-e-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 (cond - ((member type '("http" "https" "ftp")) - (concat type ":" raw-path)) - ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) - (if (file-name-absolute-p raw-path) - (concat "file://" (expand-file-name raw-path)) - (concat "file://" raw-path))) - (t raw-path))) - (email (if (string= type "mailto") - (let ((text (replace-regexp-in-string - "@" "@@" raw-path))) - (concat text (if desc (concat "," desc)))))) - protocol) - (cond - ;; Links pointing to an headline: Find destination and build - ;; appropriate referencing command. - ((member type '("custom-id" "id")) - (let ((destination (org-export-resolve-id-link link info))) - (case (org-element-type destination) - ;; Id link points to an external file. - (plain-text - (if desc (format "@uref{file://%s,%s}" destination desc) - (format "@uref{file://%s}" destination))) - ;; LINK points to an headline. Use the headline as the NODE target - (headline - (format "@ref{%s}" - (org-export-data - (org-element-property :title destination) info))) - (otherwise - (let ((path (org-export-solidify-link-text path))) - (if (not desc) (format "@ref{%s}" path) - (format "@ref{%s,,%s}" path desc))))))) - ((member type '("fuzzy")) - (let ((destination (org-export-resolve-fuzzy-link link info))) - (case (org-element-type destination) - ;; Id link points to an external file. - (plain-text - (if desc (format "@uref{file://%s,%s}" destination desc) - (format "@uref{file://%s}" destination))) - ;; LINK points to an headline. Use the headline as the NODE target - (headline - (format "@ref{%s}" - (org-export-data - (org-element-property :title destination) info))) - (otherwise - (let ((path (org-export-solidify-link-text path))) - (if (not desc) (format "@ref{%s}" path) - (format "@ref{%s,,%s}" path desc))))))) - ;; Special case for email addresses - (email - (format "@email{%s}" email)) - ;; 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 org-e-texinfo-link-with-unknown-path-format desc))))) - -;;; Macro - -(defun org-e-texinfo-macro (macro contents info) - "Transcode a MACRO element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - -;;; Menu - -(defun org-e-texinfo-make-menu (info level) - "Create the menu for inclusion in the texifo document. - -INFO is the parsed buffer that contains the headlines. LEVEL -determines whether to make the main menu, or the detailed menu. - -This is only used for generating the primary menu. In-Node menus -are generated directly." - (let* ((parse (plist-get info :parse-tree)) - ;; Top determines level to build menu from, it finds the - ;; level of the first headline in the export. - (top (org-element-map - parse 'headline - (lambda (headline) - (org-element-property :level headline)) info 't))) - (cond - ;; Generate the main menu - ((eq level 'main) - (org-e-texinfo--build-menu parse top info)) - ;; Generate the detailed (recursive) menu - ((eq level 'detailed) - ;; Requires recursion - ;;(org-e-texinfo--build-detailed-menu parse top info) - (org-e-texinfo--build-menu parse top info 'detailed)) - ;; Otherwise do nothing - (t)))) - -;;; Paragraph - -(defun org-e-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-e-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 (or (plist-get attr :indic) - org-e-texinfo-def-table-markup)) - (type (org-element-property :type plain-list)) - (table-type (or (plist-get attr :table-type) - "table")) - ;; Ensure valid texinfo table type. - (table-type (if (memq table-type '("table" "ftable" "vtable")) - table-type - "table")) - (list-type (cond - ((eq type 'ordered) "enumerate") - ((eq type 'unordered) "itemize") - ((eq type 'descriptive) table-type)))) - (format "@%s%s\n@end %s" - (if (eq type 'descriptive) - (concat list-type " " indic) - list-type) - contents - list-type))) - -;;; Plain Text - -(defun org-e-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." - ;; LaTeX into @LaTeX{} and TeX into @TeX{} - (let ((case-fold-search nil) - (start 0)) - (while (string-match "\\(\\(?:La\\)?TeX\\)" text start) - (setq text (replace-match - (format "@%s{}" (match-string 1 text)) nil t text) - start (match-end 0)))) - ;; Handle quotation marks - (setq text (org-e-texinfo--quotation-marks text info)) - ;; Convert special strings. - (when (plist-get info :with-special-strings) - (while (string-match (regexp-quote "...") text) - (setq text (replace-match "@dots{}" nil t text)))) - ;; Handle break preservation if required. - (when (plist-get info :preserve-breaks) - (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " @*\n" - text))) - ;; Return value with @ { and } protected. - (org-e-texinfo--sanitize-content text)) - -;;; Planning - -(defun org-e-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 org-e-texinfo-inactive-timestamp-format - (org-translate-time closed))))) - (let ((deadline (org-element-property :deadline planning))) - (when deadline - (concat - (format "@strong{%s} " org-deadline-string) - (format org-e-texinfo-active-timestamp-format - (org-translate-time deadline))))) - (let ((scheduled (org-element-property :scheduled planning))) - (when scheduled - (concat - (format "@strong{%s} " org-scheduled-string) - (format org-e-texinfo-active-timestamp-format - (org-translate-time scheduled))))))) - " ") - "@*")) - -;;; Property Drawer - -(defun org-e-texinfo-property-drawer (property-drawer contents info) - "Transcode a PROPERTY-DRAWER element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") - -;;; Quote Block - -(defun org-e-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* ((title (org-element-property :name quote-block)) - (start-quote (concat "@quotation" - (if title - (format " %s" title))))) - (format "%s\n%s@end quotation" start-quote contents))) - -;;; Quote Section - -(defun org-e-texinfo-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-remove-indentation - (org-element-property :value quote-section)))) - (when value (format "@verbatim\n%s@end verbatim" value)))) - -;;; Radio Target - -(defun org-e-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-export-solidify-link-text - (org-element-property :value radio-target)) - text)) - -;;; Section - -(defun org-e-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." - contents) - -;;; Special Block -;; -;; Are ignored at the moment - -;;; Src Block - -(defun org-e-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* ((lang (org-element-property :language src-block)) - (lisp-p (string-match-p "lisp" lang))) - (cond - ;; Case 1. Lisp Block - (lisp-p - (format "@lisp\n%s\n@end lisp" - (org-export-format-code-default src-block info))) - ;; Case 2. Other blocks - (t - (format "@example\n%s\n@end example" - (org-export-format-code-default src-block info)))))) - -;;; Statistics Cookie - -(defun org-e-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 -;; -;; Strikethrough is ignored - -;;; Subscript - -(defun org-e-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-e-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 -;; -;; `org-e-texinfo-table' is the entry point for table transcoding. It -;; takes care of tables with a "verbatim" attribute. Otherwise, it -;; delegates the job to either `org-e-texinfo-table--table.el-table' or -;; `org-e-texinfo-table--org-table' functions, depending of the type of -;; the table. -;; -;; `org-e-texinfo-table--align-string' is a subroutine used to build -;; alignment string for Org tables. - -(defun org-e-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." - (cond - ;; Case 1: verbatim table. - ((or org-e-texinfo-tables-verbatim - (let ((attr (mapconcat 'identity - (org-element-property :attr_latex table) - " "))) - (and attr (string-match "\\<verbatim\\>" attr)))) - (format "@verbatim \n%s\n@end verbatim" - ;; Re-create table, without affiliated keywords. - (org-trim - (org-element-interpret-data - `(table nil ,@(org-element-contents table)))))) - ;; Case 2: table.el table. Convert it using appropriate tools. - ((eq (org-element-property :type table) 'table.el) - (org-e-texinfo-table--table.el-table table contents info)) - ;; Case 3: Standard table. - (t (org-e-texinfo-table--org-table table contents info)))) - -(defun org-e-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* ((rows (org-element-map table 'table-row 'identity info)) - (collected (loop for row in rows collect - (org-element-map - row 'table-cell 'identity info))) - (number-cells (length (car collected))) - cells counts) - (loop for row in collected do - (push (mapcar (lambda (ref) - (let* ((start (org-element-property :contents-begin ref)) - (end (org-element-property :contents-end ref)) - (length (- end start))) - length)) row) cells)) - (setq cells (remove-if #'null cells)) - (push (loop for count from 0 to (- number-cells 1) collect - (loop for item in cells collect - (nth count item))) counts) - (mapconcat (lambda (size) - (make-string size ?a)) (mapcar (lambda (ref) - (apply 'max `,@ref)) (car counts)) - "} {"))) - -(defun org-e-texinfo-table--org-table (table contents info) - "Return appropriate Texinfo code for an Org table. - -TABLE is the table type element to transcode. CONTENTS is its -contents, as a string. INFO is a plist used as a communication -channel. - -This function assumes TABLE has `org' as its `:type' attribute." - (let* ((attr (org-export-read-attribute :attr_texinfo table)) - (col-width (plist-get attr :columns)) - (columns (if col-width - (format "@columnfractions %s" - col-width) - (format "{%s}" - (org-e-texinfo-table-column-widths - table info))))) - ;; Prepare the final format string for the table. - (cond - ;; Longtable. - ;; Others. - (t (concat - (format "@multitable %s\n%s@end multitable" - columns - contents)))))) - -(defun org-e-texinfo-table--table.el-table (table contents info) - "Returns nothing. - -Rather than return an invalid table, nothing is returned." - 'nil) - -;;; Table Cell - -(defun org-e-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 (if (and contents - org-e-texinfo-table-scientific-notation - (string-match orgtbl-exp-regexp contents)) - ;; Use appropriate format string for scientific - ;; notation. - (format org-e-texinfo-table-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-e-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) - (concat "@item " contents "\n"))) - -;;; Target - -(defun org-e-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-export-solidify-link-text (org-element-property :value target)))) - -;;; Timestamp - -(defun org-e-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-translate-time (org-element-property :value timestamp))) - (type (org-element-property :type timestamp))) - (cond ((memq type '(active active-range)) - (format org-e-texinfo-active-timestamp-format value)) - ((memq type '(inactive inactive-range)) - (format org-e-texinfo-inactive-timestamp-format value)) - (t (format org-e-texinfo-diary-timestamp-format value))))) - -;;; Underline -;; -;; Underline is ignored - -;;; Verbatim - -(defun org-e-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-e-texinfo--text-markup (org-element-property :value verbatim) 'verbatim)) - -;;; Verse Block - -(defun org-e-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." - ;; In a verse environment, add a line break to each newline - ;; character and change each white space at beginning of a line - ;; into a space of 1 em. Also change each blank line with - ;; a vertical space of 1 em. - (progn - (setq contents (replace-regexp-in-string - "^ *\\\\\\\\$" "\\\\vspace*{1em}" - (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents))) - (while (string-match "^[ \t]+" contents) - (let ((new-str (format "\\hspace*{%dem}" - (length (match-string 0 contents))))) - (setq contents (replace-match new-str nil t contents)))) - (format "\\begin{verse}\n%s\\end{verse}" contents))) - - -;;; Interactive functions - -(defun org-e-texinfo-export-to-texinfo - (&optional subtreep visible-only body-only ext-plist pub-dir) - "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. - -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 output file's name." - (interactive) - (let ((outfile (org-export-output-file-name ".texi" subtreep pub-dir))) - (org-export-to-file - 'e-texinfo outfile subtreep visible-only body-only ext-plist))) - -(defun org-e-texinfo-export-to-info - (&optional subtreep visible-only body-only ext-plist pub-dir) - "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. - -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) - (org-e-texinfo-compile - (org-e-texinfo-export-to-texinfo - subtreep visible-only body-only ext-plist pub-dir))) - -(defun org-e-texinfo-compile (texifile) - "Compile a texinfo file. - -TEXIFILE is the name of the file being compiled. Processing is -done through the command specified in `org-e-texinfo-info-process'. - -Return INFO file name or an error if it couldn't be produced." - (let* ((wconfig (current-window-configuration)) - (texifile (file-truename texifile)) - (base (file-name-sans-extension texifile)) - errors) - (message (format "Processing Texinfo file %s ..." texifile)) - (unwind-protect - (progn - (cond - ;; A function is provided: Apply it. - ((functionp org-e-texinfo-info-process) - (funcall org-e-texinfo-info-process (shell-quote-argument texifile))) - ;; A list is provided: Replace %b, %f and %o with appropriate - ;; values in each command before applying it. Output is - ;; redirected to "*Org INFO Texinfo Output*" buffer. - ((consp org-e-texinfo-info-process) - (let* ((out-dir (or (file-name-directory texifile) "./")) - (outbuf (get-buffer-create "*Org Info Texinfo Output*"))) - (mapc - (lambda (command) - (shell-command - (replace-regexp-in-string - "%b" (shell-quote-argument base) - (replace-regexp-in-string - "%f" (shell-quote-argument texifile) - (replace-regexp-in-string - "%o" (shell-quote-argument out-dir) command t t) t t) t t) - outbuf)) - org-e-texinfo-info-process) - ;; Collect standard errors from output buffer. - (setq errors (org-e-texinfo-collect-errors outbuf)))) - (t (error "No valid command to process to Info"))) - (let ((infofile (concat base ".info"))) - ;; Check for process failure. Provide collected errors if - ;; possible. - (if (not (file-exists-p infofile)) - (error (concat (format "INFO file %s wasn't produced" infofile) - (when errors (concat ": " errors)))) - ;; Else remove log files, when specified, and signal end of - ;; process to user, along with any error encountered. - (message (concat "Process completed" - (if (not errors) "." - (concat " with errors: " errors))))) - ;; Return output file name. - infofile)) - (set-window-configuration wconfig)))) - -(defun org-e-texinfo-collect-errors (buffer) - "Collect some kind of errors from \"makeinfo\" command output. - -BUFFER is the buffer containing output. - -Return collected error types as a string, or nil if there was -none." - (with-current-buffer buffer - (save-excursion - (goto-char (point-min)) - ;; Find final "makeinfo" run. - (when t - (let ((case-fold-search t) - (errors "")) - (when (save-excursion - (re-search-forward "perhaps incorrect sectioning?" nil t)) - (setq errors (concat errors " [incorrect sectionnng]"))) - (when (save-excursion - (re-search-forward "missing close brace" nil t)) - (setq errors (concat errors " [syntax error]"))) - (when (save-excursion - (re-search-forward "Unknown command" nil t)) - (setq errors (concat errors " [undefined @command]"))) - (when (save-excursion - (re-search-forward "No matching @end" nil t)) - (setq errors (concat errors " [block incomplete]"))) - (when (save-excursion - (re-search-forward "requires a sectioning" nil t)) - (setq errors (concat errors " [invalid section command]"))) - (when (save-excursion - (re-search-forward "\\[unexpected\]" nil t)) - (setq errors (concat errors " [unexpected error]"))) - (when (save-excursion - (re-search-forward "misplaced " nil t)) - (setq errors (concat errors " [syntax error]"))) - (and (org-string-nw-p errors) (org-trim errors))))))) - -(provide 'org-e-texinfo) -;;; org-e-texinfo.el ends here |