From 6ea9d8c827c5edbae37d80e068d35c883b119ddb Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Mon, 23 Jul 2012 14:06:13 +0200 Subject: [PATCH] org-export: `org-export-define-backend': the standard way to create a back-end * contrib/lisp/org-export.el (org-export-define-backend): New macro. * contrib/lisp/org-e-ascii.el: Use new macro. * contrib/lisp/org-e-html.el: Use new macro. * contrib/lisp/org-e-latex.el: Use new macro. * contrib/lisp/org-e-odt.el: Use new macro. * contrib/lisp/org-element.el (org-element-block-name-alist): Remove hard-coded export block names from variable, since they are added automatically by `org-export-define-backend'. * testing/lisp/test-org-element.el: Update test. --- contrib/lisp/org-e-ascii.el | 125 +++++++++--------- contrib/lisp/org-e-html.el | 187 ++++++++++++--------------- contrib/lisp/org-e-latex.el | 123 +++++++++--------- contrib/lisp/org-e-odt.el | 123 +++++++++--------- contrib/lisp/org-element.el | 7 +- contrib/lisp/org-export.el | 209 +++++++++++++++++++++++++------ testing/lisp/test-org-element.el | 22 +++- 7 files changed, 443 insertions(+), 353 deletions(-) diff --git a/contrib/lisp/org-e-ascii.el b/contrib/lisp/org-e-ascii.el index 905f4e796..7c2187f4b 100644 --- a/contrib/lisp/org-e-ascii.el +++ b/contrib/lisp/org-e-ascii.el @@ -47,73 +47,64 @@ ;; We also install a filter for headlines and sections, in order to ;; control blank lines separating them in output string. -(defvar org-e-ascii-translate-alist - '((babel-call . org-e-ascii-babel-call) - (bold . org-e-ascii-bold) - (center-block . org-e-ascii-center-block) - (clock . org-e-ascii-clock) - (code . org-e-ascii-code) - (comment . org-e-ascii-comment) - (comment-block . org-e-ascii-comment-block) - (drawer . org-e-ascii-drawer) - (dynamic-block . org-e-ascii-dynamic-block) - (entity . org-e-ascii-entity) - (example-block . org-e-ascii-example-block) - (export-block . org-e-ascii-export-block) - (export-snippet . org-e-ascii-export-snippet) - (fixed-width . org-e-ascii-fixed-width) - (footnote-definition . org-e-ascii-footnote-definition) - (footnote-reference . org-e-ascii-footnote-reference) - (headline . org-e-ascii-headline) - (horizontal-rule . org-e-ascii-horizontal-rule) - (inline-babel-call . org-e-ascii-inline-babel-call) - (inline-src-block . org-e-ascii-inline-src-block) - (inlinetask . org-e-ascii-inlinetask) - (italic . org-e-ascii-italic) - (item . org-e-ascii-item) - (keyword . org-e-ascii-keyword) - (latex-environment . org-e-ascii-latex-environment) - (latex-fragment . org-e-ascii-latex-fragment) - (line-break . org-e-ascii-line-break) - (link . org-e-ascii-link) - (macro . org-e-ascii-macro) - (paragraph . org-e-ascii-paragraph) - (plain-list . org-e-ascii-plain-list) - (plain-text . org-e-ascii-plain-text) - (planning . org-e-ascii-planning) - (property-drawer . org-e-ascii-property-drawer) - (quote-block . org-e-ascii-quote-block) - (quote-section . org-e-ascii-quote-section) - (radio-target . org-e-ascii-radio-target) - (section . org-e-ascii-section) - (special-block . org-e-ascii-special-block) - (src-block . org-e-ascii-src-block) - (statistics-cookie . org-e-ascii-statistics-cookie) - (strike-through . org-e-ascii-strike-through) - (subscript . org-e-ascii-subscript) - (superscript . org-e-ascii-superscript) - (table . org-e-ascii-table) - (table-cell . org-e-ascii-table-cell) - (table-row . org-e-ascii-table-row) - (target . org-e-ascii-target) - (template . org-e-ascii-template) - (timestamp . org-e-ascii-timestamp) - (underline . org-e-ascii-underline) - (verbatim . org-e-ascii-verbatim) - (verse-block . org-e-ascii-verse-block)) - "Alist between element or object types and translators.") - -(defconst org-e-ascii-options-alist - '((:ascii-charset nil nil org-e-ascii-charset)) - "Alist between ASCII export properties and ways to set them. -See `org-export-options-alist' for more information on the -structure of the values.") - -(defconst org-e-ascii-filters-alist - '((:filter-headline . org-e-ascii-filter-headline-blank-lines) - (:filter-section . org-e-ascii-filter-headline-blank-lines)) - "Alist between filters keywords and back-end specific filters. -See `org-export-filters-alist' for more information.") +(org-export-define-backend e-ascii + ((babel-call . org-e-ascii-babel-call) + (bold . org-e-ascii-bold) + (center-block . org-e-ascii-center-block) + (clock . org-e-ascii-clock) + (code . org-e-ascii-code) + (comment . org-e-ascii-comment) + (comment-block . org-e-ascii-comment-block) + (drawer . org-e-ascii-drawer) + (dynamic-block . org-e-ascii-dynamic-block) + (entity . org-e-ascii-entity) + (example-block . org-e-ascii-example-block) + (export-block . org-e-ascii-export-block) + (export-snippet . org-e-ascii-export-snippet) + (fixed-width . org-e-ascii-fixed-width) + (footnote-definition . org-e-ascii-footnote-definition) + (footnote-reference . org-e-ascii-footnote-reference) + (headline . org-e-ascii-headline) + (horizontal-rule . org-e-ascii-horizontal-rule) + (inline-babel-call . org-e-ascii-inline-babel-call) + (inline-src-block . org-e-ascii-inline-src-block) + (inlinetask . org-e-ascii-inlinetask) + (italic . org-e-ascii-italic) + (item . org-e-ascii-item) + (keyword . org-e-ascii-keyword) + (latex-environment . org-e-ascii-latex-environment) + (latex-fragment . org-e-ascii-latex-fragment) + (line-break . org-e-ascii-line-break) + (link . org-e-ascii-link) + (macro . org-e-ascii-macro) + (paragraph . org-e-ascii-paragraph) + (plain-list . org-e-ascii-plain-list) + (plain-text . org-e-ascii-plain-text) + (planning . org-e-ascii-planning) + (property-drawer . org-e-ascii-property-drawer) + (quote-block . org-e-ascii-quote-block) + (quote-section . org-e-ascii-quote-section) + (radio-target . org-e-ascii-radio-target) + (section . org-e-ascii-section) + (special-block . org-e-ascii-special-block) + (src-block . org-e-ascii-src-block) + (statistics-cookie . org-e-ascii-statistics-cookie) + (strike-through . org-e-ascii-strike-through) + (subscript . org-e-ascii-subscript) + (superscript . org-e-ascii-superscript) + (table . org-e-ascii-table) + (table-cell . org-e-ascii-table-cell) + (table-row . org-e-ascii-table-row) + (target . org-e-ascii-target) + (template . org-e-ascii-template) + (timestamp . org-e-ascii-timestamp) + (underline . org-e-ascii-underline) + (verbatim . org-e-ascii-verbatim) + (verse-block . org-e-ascii-verse-block)) + :export-block "ASCII" + :filters-alist ((:filter-headline . org-e-ascii-filter-headline-blank-lines) + (:filter-section . org-e-ascii-filter-headline-blank-lines)) + :options-alist ((:ascii-charset nil nil org-e-ascii-charset))) diff --git a/contrib/lisp/org-e-html.el b/contrib/lisp/org-e-html.el index 7eaa6e262..e813c3383 100644 --- a/contrib/lisp/org-e-html.el +++ b/contrib/lisp/org-e-html.el @@ -51,113 +51,86 @@ ;;; Define Back-End -(defvar org-e-html-translate-alist - '((babel-call . org-e-html-babel-call) - (bold . org-e-html-bold) - (center-block . org-e-html-center-block) - (clock . org-e-html-clock) - (code . org-e-html-code) - (comment . org-e-html-comment) - (comment-block . org-e-html-comment-block) - (drawer . org-e-html-drawer) - (dynamic-block . org-e-html-dynamic-block) - (entity . org-e-html-entity) - (example-block . org-e-html-example-block) - (export-block . org-e-html-export-block) - (export-snippet . org-e-html-export-snippet) - (fixed-width . org-e-html-fixed-width) - (footnote-definition . org-e-html-footnote-definition) - (footnote-reference . org-e-html-footnote-reference) - (headline . org-e-html-headline) - (horizontal-rule . org-e-html-horizontal-rule) - (inline-babel-call . org-e-html-inline-babel-call) - (inline-src-block . org-e-html-inline-src-block) - (inlinetask . org-e-html-inlinetask) - (italic . org-e-html-italic) - (item . org-e-html-item) - (keyword . org-e-html-keyword) - (latex-environment . org-e-html-latex-environment) - (latex-fragment . org-e-html-latex-fragment) - (line-break . org-e-html-line-break) - (link . org-e-html-link) - (macro . org-e-html-macro) - (paragraph . org-e-html-paragraph) - (plain-list . org-e-html-plain-list) - (plain-text . org-e-html-plain-text) - (planning . org-e-html-planning) - (property-drawer . org-e-html-property-drawer) - (quote-block . org-e-html-quote-block) - (quote-section . org-e-html-quote-section) - (radio-target . org-e-html-radio-target) - (section . org-e-html-section) - (special-block . org-e-html-special-block) - (src-block . org-e-html-src-block) - (statistics-cookie . org-e-html-statistics-cookie) - (strike-through . org-e-html-strike-through) - (subscript . org-e-html-subscript) - (superscript . org-e-html-superscript) - (table . org-e-html-table) - (table-cell . org-e-html-table-cell) - (table-row . org-e-html-table-row) - (target . org-e-html-target) - (template . org-e-html-template) - (timestamp . org-e-html-timestamp) - (underline . org-e-html-underline) - (verbatim . org-e-html-verbatim) - (verse-block . org-e-html-verse-block)) - "Alist between element or object types and translators.") - -;; FIXME (`org-e-html-options-alist'): Prefix KEYWORD and OPTION with -;; "HTML_". Prefix corresponding properties with `:html-". If such a -;; renaming is taken up, some changes will be required in -;; `org-jsinfo.el', I think. So defer renaming for now. - -(defconst org-e-html-options-alist - '((:agenda-style nil nil org-agenda-export-html-style) - (:creator "CREATOR" nil org-e-html-creator-string) - (:convert-org-links nil nil org-e-html-link-org-files-as-html) - ;; (:expand-quoted-html nil "@" org-e-html-expand) - (:inline-images nil nil org-e-html-inline-images) - (:link-home "LINK_HOME" nil org-e-html-link-home) - (:link-up "LINK_UP" nil org-e-html-link-up) - (:style nil nil org-e-html-style) - (:style-extra "STYLE" nil org-e-html-style-extra newline) - (:style-include-default nil nil org-e-html-style-include-default) - (:style-include-scripts nil nil org-e-html-style-include-scripts) - ;; (:timestamp nil nil org-e-html-with-timestamp) - (:html-extension nil nil org-e-html-extension) - (:html-postamble nil nil org-e-html-postamble) - (:html-preamble nil nil org-e-html-preamble) - (:html-table-tag nil nil org-e-html-table-tag) - (:xml-declaration nil nil org-e-html-xml-declaration) - (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments) - (:mathjax "MATHJAX" nil "" space)) - "Alist between HTML export properties and ways to set them. -This variable is the HTML-specific counterpart of -`org-export-options-alist'. - -The CAR of the alist is the property name, and the CDR is a list -like (KEYWORD OPTION DEFAULT BEHAVIOUR) where: - -KEYWORD is a string representing a buffer keyword, or nil. -OPTION is a string that could be found in an #+OPTIONS: line. -DEFAULT is the default value for the property. -BEHAVIOUR determine how Org should handle multiple keywords for -the same property. It is a symbol among: - nil Keep old value and discard the new one. - t Replace old value with the new one. - `space' Concatenate the values, separating them with a space. - `newline' Concatenate the values, separating them with - a newline. - `split' Split values at white spaces, and cons them to the - previous list. - -KEYWORD and OPTION have precedence over DEFAULT.") - -(defconst org-e-html-filters-alist - '((:filter-final-output . org-e-html-final-function)) - "Alist between filters keywords and back-end specific filters. -See `org-export-filters-alist' for more information.") +(org-export-define-backend e-html + ((babel-call . org-e-html-babel-call) + (bold . org-e-html-bold) + (center-block . org-e-html-center-block) + (clock . org-e-html-clock) + (code . org-e-html-code) + (comment . org-e-html-comment) + (comment-block . org-e-html-comment-block) + (drawer . org-e-html-drawer) + (dynamic-block . org-e-html-dynamic-block) + (entity . org-e-html-entity) + (example-block . org-e-html-example-block) + (export-block . org-e-html-export-block) + (export-snippet . org-e-html-export-snippet) + (fixed-width . org-e-html-fixed-width) + (footnote-definition . org-e-html-footnote-definition) + (footnote-reference . org-e-html-footnote-reference) + (headline . org-e-html-headline) + (horizontal-rule . org-e-html-horizontal-rule) + (inline-babel-call . org-e-html-inline-babel-call) + (inline-src-block . org-e-html-inline-src-block) + (inlinetask . org-e-html-inlinetask) + (italic . org-e-html-italic) + (item . org-e-html-item) + (keyword . org-e-html-keyword) + (latex-environment . org-e-html-latex-environment) + (latex-fragment . org-e-html-latex-fragment) + (line-break . org-e-html-line-break) + (link . org-e-html-link) + (macro . org-e-html-macro) + (paragraph . org-e-html-paragraph) + (plain-list . org-e-html-plain-list) + (plain-text . org-e-html-plain-text) + (planning . org-e-html-planning) + (property-drawer . org-e-html-property-drawer) + (quote-block . org-e-html-quote-block) + (quote-section . org-e-html-quote-section) + (radio-target . org-e-html-radio-target) + (section . org-e-html-section) + (special-block . org-e-html-special-block) + (src-block . org-e-html-src-block) + (statistics-cookie . org-e-html-statistics-cookie) + (strike-through . org-e-html-strike-through) + (subscript . org-e-html-subscript) + (superscript . org-e-html-superscript) + (table . org-e-html-table) + (table-cell . org-e-html-table-cell) + (table-row . org-e-html-table-row) + (target . org-e-html-target) + (template . org-e-html-template) + (timestamp . org-e-html-timestamp) + (underline . org-e-html-underline) + (verbatim . org-e-html-verbatim) + (verse-block . org-e-html-verse-block)) + :export-block "HTML" + :filters-alist ((:filter-final-output . org-e-html-final-function)) + :options-alist + ;; FIXME: Prefix KEYWORD and OPTION with "HTML_". Prefix + ;; corresponding properties with `:html-". If such a renaming is + ;; taken up, some changes will be required in `org-jsinfo.el', + ;; I think. So defer renaming for now. + ((:agenda-style nil nil org-agenda-export-html-style) + (:creator "CREATOR" nil org-e-html-creator-string) + (:convert-org-links nil nil org-e-html-link-org-files-as-html) + ;; (:expand-quoted-html nil "@" org-e-html-expand) + (:inline-images nil nil org-e-html-inline-images) + (:link-home "LINK_HOME" nil org-e-html-link-home) + (:link-up "LINK_UP" nil org-e-html-link-up) + (:style nil nil org-e-html-style) + (:style-extra "STYLE" nil org-e-html-style-extra newline) + (:style-include-default nil nil org-e-html-style-include-default) + (:style-include-scripts nil nil org-e-html-style-include-scripts) + ;; (:timestamp nil nil org-e-html-with-timestamp) + (:html-extension nil nil org-e-html-extension) + (:html-postamble nil nil org-e-html-postamble) + (:html-preamble nil nil org-e-html-preamble) + (:html-table-tag nil nil org-e-html-table-tag) + (:xml-declaration nil nil org-e-html-xml-declaration) + (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments) + (:mathjax "MATHJAX" nil "" space))) diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el index 564d6b6ba..0ea20d881 100644 --- a/contrib/lisp/org-e-latex.el +++ b/contrib/lisp/org-e-latex.el @@ -46,70 +46,65 @@ ;;; Define Back-End -(defvar org-e-latex-translate-alist - '((babel-call . org-e-latex-babel-call) - (bold . org-e-latex-bold) - (center-block . org-e-latex-center-block) - (clock . org-e-latex-clock) - (code . org-e-latex-code) - (comment . org-e-latex-comment) - (comment-block . org-e-latex-comment-block) - (drawer . org-e-latex-drawer) - (dynamic-block . org-e-latex-dynamic-block) - (entity . org-e-latex-entity) - (example-block . org-e-latex-example-block) - (export-block . org-e-latex-export-block) - (export-snippet . org-e-latex-export-snippet) - (fixed-width . org-e-latex-fixed-width) - (footnote-definition . org-e-latex-footnote-definition) - (footnote-reference . org-e-latex-footnote-reference) - (headline . org-e-latex-headline) - (horizontal-rule . org-e-latex-horizontal-rule) - (inline-babel-call . org-e-latex-inline-babel-call) - (inline-src-block . org-e-latex-inline-src-block) - (inlinetask . org-e-latex-inlinetask) - (italic . org-e-latex-italic) - (item . org-e-latex-item) - (keyword . org-e-latex-keyword) - (latex-environment . org-e-latex-latex-environment) - (latex-fragment . org-e-latex-latex-fragment) - (line-break . org-e-latex-line-break) - (link . org-e-latex-link) - (macro . org-e-latex-macro) - (paragraph . org-e-latex-paragraph) - (plain-list . org-e-latex-plain-list) - (plain-text . org-e-latex-plain-text) - (planning . org-e-latex-planning) - (property-drawer . org-e-latex-property-drawer) - (quote-block . org-e-latex-quote-block) - (quote-section . org-e-latex-quote-section) - (radio-target . org-e-latex-radio-target) - (section . org-e-latex-section) - (special-block . org-e-latex-special-block) - (src-block . org-e-latex-src-block) - (statistics-cookie . org-e-latex-statistics-cookie) - (strike-through . org-e-latex-strike-through) - (subscript . org-e-latex-subscript) - (superscript . org-e-latex-superscript) - (table . org-e-latex-table) - (table-cell . org-e-latex-table-cell) - (table-row . org-e-latex-table-row) - (target . org-e-latex-target) - (template . org-e-latex-template) - (timestamp . org-e-latex-timestamp) - (underline . org-e-latex-underline) - (verbatim . org-e-latex-verbatim) - (verse-block . org-e-latex-verse-block)) - "Alist between element or object types and translators.") - -(defconst org-e-latex-options-alist - '((:date "DATE" nil org-e-latex-date-format t) - (:latex-class "LATEX_CLASS" nil org-e-latex-default-class t) - (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) - (:latex-header-extra "LATEX_HEADER" nil nil newline)) - "Alist between LaTeX export properties and ways to set them. -See `org-export-options-alist' for more information on the -structure of the values.") +(org-export-define-backend e-latex + ((babel-call . org-e-latex-babel-call) + (bold . org-e-latex-bold) + (center-block . org-e-latex-center-block) + (clock . org-e-latex-clock) + (code . org-e-latex-code) + (comment . org-e-latex-comment) + (comment-block . org-e-latex-comment-block) + (drawer . org-e-latex-drawer) + (dynamic-block . org-e-latex-dynamic-block) + (entity . org-e-latex-entity) + (example-block . org-e-latex-example-block) + (export-block . org-e-latex-export-block) + (export-snippet . org-e-latex-export-snippet) + (fixed-width . org-e-latex-fixed-width) + (footnote-definition . org-e-latex-footnote-definition) + (footnote-reference . org-e-latex-footnote-reference) + (headline . org-e-latex-headline) + (horizontal-rule . org-e-latex-horizontal-rule) + (inline-babel-call . org-e-latex-inline-babel-call) + (inline-src-block . org-e-latex-inline-src-block) + (inlinetask . org-e-latex-inlinetask) + (italic . org-e-latex-italic) + (item . org-e-latex-item) + (keyword . org-e-latex-keyword) + (latex-environment . org-e-latex-latex-environment) + (latex-fragment . org-e-latex-latex-fragment) + (line-break . org-e-latex-line-break) + (link . org-e-latex-link) + (macro . org-e-latex-macro) + (paragraph . org-e-latex-paragraph) + (plain-list . org-e-latex-plain-list) + (plain-text . org-e-latex-plain-text) + (planning . org-e-latex-planning) + (property-drawer . org-e-latex-property-drawer) + (quote-block . org-e-latex-quote-block) + (quote-section . org-e-latex-quote-section) + (radio-target . org-e-latex-radio-target) + (section . org-e-latex-section) + (special-block . org-e-latex-special-block) + (src-block . org-e-latex-src-block) + (statistics-cookie . org-e-latex-statistics-cookie) + (strike-through . org-e-latex-strike-through) + (subscript . org-e-latex-subscript) + (superscript . org-e-latex-superscript) + (table . org-e-latex-table) + (table-cell . org-e-latex-table-cell) + (table-row . org-e-latex-table-row) + (target . org-e-latex-target) + (template . org-e-latex-template) + (timestamp . org-e-latex-timestamp) + (underline . org-e-latex-underline) + (verbatim . org-e-latex-verbatim) + (verse-block . org-e-latex-verse-block)) + :export-block "LATEX" + :options-alist ((:date "DATE" nil org-e-latex-date-format t) + (:latex-class "LATEX_CLASS" nil org-e-latex-default-class t) + (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) + (:latex-header-extra "LATEX_HEADER" nil nil newline))) diff --git a/contrib/lisp/org-e-odt.el b/contrib/lisp/org-e-odt.el index daffe9cb8..f76d550ef 100644 --- a/contrib/lisp/org-e-odt.el +++ b/contrib/lisp/org-e-odt.el @@ -33,72 +33,65 @@ ;;; Define Back-End -(defvar org-e-odt-translate-alist - '((babel-call . org-e-odt-babel-call) - (bold . org-e-odt-bold) - (center-block . org-e-odt-center-block) - (clock . org-e-odt-clock) - (code . org-e-odt-code) - (comment . org-e-odt-comment) - (comment-block . org-e-odt-comment-block) - (drawer . org-e-odt-drawer) - (dynamic-block . org-e-odt-dynamic-block) - (entity . org-e-odt-entity) - (example-block . org-e-odt-example-block) - (export-block . org-e-odt-export-block) - (export-snippet . org-e-odt-export-snippet) - (fixed-width . org-e-odt-fixed-width) - (footnote-definition . org-e-odt-footnote-definition) - (footnote-reference . org-e-odt-footnote-reference) - (headline . org-e-odt-headline) - (horizontal-rule . org-e-odt-horizontal-rule) - (inline-babel-call . org-e-odt-inline-babel-call) - (inline-src-block . org-e-odt-inline-src-block) - (inlinetask . org-e-odt-inlinetask) - (italic . org-e-odt-italic) - (item . org-e-odt-item) - (keyword . org-e-odt-keyword) - (latex-environment . org-e-odt-latex-environment) - (latex-fragment . org-e-odt-latex-fragment) - (line-break . org-e-odt-line-break) - (link . org-e-odt-link) - (macro . org-e-odt-macro) - (paragraph . org-e-odt-paragraph) - (plain-list . org-e-odt-plain-list) - (plain-text . org-e-odt-plain-text) - (planning . org-e-odt-planning) - (property-drawer . org-e-odt-property-drawer) - (quote-block . org-e-odt-quote-block) - (quote-section . org-e-odt-quote-section) - (radio-target . org-e-odt-radio-target) - (section . org-e-odt-section) - (special-block . org-e-odt-special-block) - (src-block . org-e-odt-src-block) - (statistics-cookie . org-e-odt-statistics-cookie) - (strike-through . org-e-odt-strike-through) - (subscript . org-e-odt-subscript) - (superscript . org-e-odt-superscript) - (table . org-e-odt-table) - (table-cell . org-e-odt-table-cell) - (table-row . org-e-odt-table-row) - (target . org-e-odt-target) - (template . org-e-odt-template) - (timestamp . org-e-odt-timestamp) - (underline . org-e-odt-underline) - (verbatim . org-e-odt-verbatim) - (verse-block . org-e-odt-verse-block)) - "Alist between element or object types and translators.") +(org-export-define-backend e-odt + ((babel-call . org-e-odt-babel-call) + (bold . org-e-odt-bold) + (center-block . org-e-odt-center-block) + (clock . org-e-odt-clock) + (code . org-e-odt-code) + (comment . org-e-odt-comment) + (comment-block . org-e-odt-comment-block) + (drawer . org-e-odt-drawer) + (dynamic-block . org-e-odt-dynamic-block) + (entity . org-e-odt-entity) + (example-block . org-e-odt-example-block) + (export-block . org-e-odt-export-block) + (export-snippet . org-e-odt-export-snippet) + (fixed-width . org-e-odt-fixed-width) + (footnote-definition . org-e-odt-footnote-definition) + (footnote-reference . org-e-odt-footnote-reference) + (headline . org-e-odt-headline) + (horizontal-rule . org-e-odt-horizontal-rule) + (inline-babel-call . org-e-odt-inline-babel-call) + (inline-src-block . org-e-odt-inline-src-block) + (inlinetask . org-e-odt-inlinetask) + (italic . org-e-odt-italic) + (item . org-e-odt-item) + (keyword . org-e-odt-keyword) + (latex-environment . org-e-odt-latex-environment) + (latex-fragment . org-e-odt-latex-fragment) + (line-break . org-e-odt-line-break) + (link . org-e-odt-link) + (macro . org-e-odt-macro) + (paragraph . org-e-odt-paragraph) + (plain-list . org-e-odt-plain-list) + (plain-text . org-e-odt-plain-text) + (planning . org-e-odt-planning) + (property-drawer . org-e-odt-property-drawer) + (quote-block . org-e-odt-quote-block) + (quote-section . org-e-odt-quote-section) + (radio-target . org-e-odt-radio-target) + (section . org-e-odt-section) + (special-block . org-e-odt-special-block) + (src-block . org-e-odt-src-block) + (statistics-cookie . org-e-odt-statistics-cookie) + (strike-through . org-e-odt-strike-through) + (subscript . org-e-odt-subscript) + (superscript . org-e-odt-superscript) + (table . org-e-odt-table) + (table-cell . org-e-odt-table-cell) + (table-row . org-e-odt-table-row) + (target . org-e-odt-target) + (template . org-e-odt-template) + (timestamp . org-e-odt-timestamp) + (underline . org-e-odt-underline) + (verbatim . org-e-odt-verbatim) + (verse-block . org-e-odt-verse-block)) + :export-block "ODT" + :options-alist + ((:odt-styles-file "ODT_STYLES_FILE" nil nil t) + (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments))) -(defconst org-e-odt-options-alist - '( - ;; (:agenda-style nil nil org-agenda-export-html-style) - ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand) - ;; ;; (:timestamp nil nil org-e-odt-with-timestamp) - (:odt-styles-file "ODT_STYLES_FILE" nil nil t) - (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments)) - "Alist between ODT export properties and ways to set them. -See `org-export-options-alist' for more information on the -structure of the values.") ;;; Dependencies diff --git a/contrib/lisp/org-element.el b/contrib/lisp/org-element.el index bc04cb366..8f460471d 100644 --- a/contrib/lisp/org-element.el +++ b/contrib/lisp/org-element.el @@ -192,14 +192,9 @@ regexp matching one object can also match the other object.") "List of recursive object types.") (defconst org-element-block-name-alist - '(("ASCII" . org-element-export-block-parser) - ("CENTER" . org-element-center-block-parser) + '(("CENTER" . org-element-center-block-parser) ("COMMENT" . org-element-comment-block-parser) - ("DOCBOOK" . org-element-export-block-parser) ("EXAMPLE" . org-element-example-block-parser) - ("HTML" . org-element-export-block-parser) - ("LATEX" . org-element-export-block-parser) - ("ODT" . org-element-export-block-parser) ("QUOTE" . org-element-quote-block-parser) ("SRC" . org-element-src-block-parser) ("VERSE" . org-element-verse-block-parser)) diff --git a/contrib/lisp/org-export.el b/contrib/lisp/org-export.el index ef739d8ad..246cb7a77 100644 --- a/contrib/lisp/org-export.el +++ b/contrib/lisp/org-export.el @@ -47,53 +47,23 @@ ;; The core function is `org-export-as'. It returns the transcoded ;; buffer as a string. ;; -;; A back-end is defined through one mandatory variable: his -;; translation table. Its name is always -;; `org-BACKEND-translate-alist' where BACKEND stands for the name -;; chosen for the back-end. Its value is an alist whose keys are -;; elements and objects types and values translator functions. +;; An export back-end is defined with `org-export-define-backend', +;; which sets one mandatory variable: his translation table. Its name +;; is always `org-BACKEND-translate-alist' where BACKEND stands for +;; the name chosen for the back-end. Its value is an alist whose keys +;; are elements and objects types and values translator functions. +;; See function's docstring for more information about translators. ;; -;; These functions should return a string without any trailing space, -;; or nil. They must accept three arguments: the object or element -;; itself, its contents or nil when it isn't recursive and the -;; property list used as a communication channel. -;; -;; Contents, when not nil, are stripped from any global indentation -;; (although the relative one is preserved). They also always end -;; with a single newline character. -;; -;; If, for a given type, no function is found, that element or object -;; type will simply be ignored, along with any blank line or white -;; space at its end. The same will happen if the function returns the -;; nil value. If that function returns the empty string, the type -;; will be ignored, but the blank lines or white spaces will be kept. -;; -;; In addition to element and object types, one function can be -;; associated to the `template' symbol and another one to the -;; `plain-text' symbol. -;; -;; The former returns the final transcoded string, and can be used to -;; add a preamble and a postamble to document's body. It must accept -;; two arguments: the transcoded string and the property list -;; containing export options. -;; -;; The latter, when defined, is to be called on every text not -;; recognized as an element or an object. It must accept two -;; arguments: the text string and the information channel. It is an -;; appropriate place to protect special chars relative to the -;; back-end. -;; -;; Optionally, a back-end can support specific buffer keywords and -;; OPTION keyword's items by setting `org-BACKEND-filters-alist' -;; variable. Refer to `org-export-options-alist' documentation for -;; more information about its value. +;; Optionally, `org-export-define-backend' can also support specific +;; buffer keywords, OPTION keyword's items and filters. Also refer to +;; function documentation for more information. ;; ;; If the new back-end shares most properties with another one, ;; `org-export-define-derived-backend' can be used to simplify the ;; process. ;; ;; Any back-end can define its own variables. Among them, those -;; customizables should belong to the `org-export-BACKEND' group. +;; customizable should belong to the `org-export-BACKEND' group. ;; ;; Tools for common tasks across back-ends are implemented in the ;; penultimate part of this file. A dispatcher for standard back-ends @@ -723,6 +693,165 @@ standard mode." ;;; Defining New Back-ends +(defmacro org-export-define-backend (backend translators &rest body) + "Define a new back-end BACKEND. + +TRANSLATORS is an alist between object or element types and +functions handling them. + +These functions should return a string without any trailing +space, or nil. They must accept three arguments: the object or +element itself, its contents or nil when it isn't recursive and +the property list used as a communication channel. + +Contents, when not nil, are stripped from any global indentation +\(although the relative one is preserved). They also always end +with a single newline character. + +If, for a given type, no function is found, that element or +object type will simply be ignored, along with any blank line or +white space at its end. The same will happen if the function +returns the nil value. If that function returns the empty +string, the type will be ignored, but the blank lines or white +spaces will be kept. + +In addition to element and object types, one function can be +associated to the `template' symbol and another one to the +`plain-text' symbol. + +The former returns the final transcoded string, and can be used +to add a preamble and a postamble to document's body. It must +accept two arguments: the transcoded string and the property list +containing export options. + +The latter, when defined, is to be called on every text not +recognized as an element or an object. It must accept two +arguments: the text string and the information channel. It is an +appropriate place to protect special chars relative to the +back-end. + +BODY can start with pre-defined keyword arguments. The following +keywords are understood: + + :export-block + + String, or list of strings, representing block names that + will not be parsed. This is used to specify blocks that will + contain raw code specific to the back-end. These blocks + still have to be handled by the relative `export-block' type + translator. + + :filters-alist + + Alist between filters and function, or list of functions, + specific to the back-end. See `org-export-filters-alist' for + a list of all allowed filters. + + :options-alist + + Alist between back-end specific properties introduced in + communication channel and how their value are acquired. See + `org-export-options-alist' for more information about + structure of the values. + +As an example, here is how the `e-ascii' back-end is defined: + +\(org-export-define-backend e-ascii + \((babel-call . org-e-ascii-babel-call) + \(bold . org-e-ascii-bold) + \(center-block . org-e-ascii-center-block) + \(clock . org-e-ascii-clock) + \(code . org-e-ascii-code) + \(comment . org-e-ascii-comment) + \(comment-block . org-e-ascii-comment-block) + \(drawer . org-e-ascii-drawer) + \(dynamic-block . org-e-ascii-dynamic-block) + \(entity . org-e-ascii-entity) + \(example-block . org-e-ascii-example-block) + \(export-block . org-e-ascii-export-block) + \(export-snippet . org-e-ascii-export-snippet) + \(fixed-width . org-e-ascii-fixed-width) + \(footnote-definition . org-e-ascii-footnote-definition) + \(footnote-reference . org-e-ascii-footnote-reference) + \(headline . org-e-ascii-headline) + \(horizontal-rule . org-e-ascii-horizontal-rule) + \(inline-babel-call . org-e-ascii-inline-babel-call) + \(inline-src-block . org-e-ascii-inline-src-block) + \(inlinetask . org-e-ascii-inlinetask) + \(italic . org-e-ascii-italic) + \(item . org-e-ascii-item) + \(keyword . org-e-ascii-keyword) + \(latex-environment . org-e-ascii-latex-environment) + \(latex-fragment . org-e-ascii-latex-fragment) + \(line-break . org-e-ascii-line-break) + \(link . org-e-ascii-link) + \(macro . org-e-ascii-macro) + \(paragraph . org-e-ascii-paragraph) + \(plain-list . org-e-ascii-plain-list) + \(plain-text . org-e-ascii-plain-text) + \(planning . org-e-ascii-planning) + \(property-drawer . org-e-ascii-property-drawer) + \(quote-block . org-e-ascii-quote-block) + \(quote-section . org-e-ascii-quote-section) + \(radio-target . org-e-ascii-radio-target) + \(section . org-e-ascii-section) + \(special-block . org-e-ascii-special-block) + \(src-block . org-e-ascii-src-block) + \(statistics-cookie . org-e-ascii-statistics-cookie) + \(strike-through . org-e-ascii-strike-through) + \(subscript . org-e-ascii-subscript) + \(superscript . org-e-ascii-superscript) + \(table . org-e-ascii-table) + \(table-cell . org-e-ascii-table-cell) + \(table-row . org-e-ascii-table-row) + \(target . org-e-ascii-target) + \(template . org-e-ascii-template) + \(timestamp . org-e-ascii-timestamp) + \(underline . org-e-ascii-underline) + \(verbatim . org-e-ascii-verbatim) + \(verse-block . org-e-ascii-verse-block)) + :export-block \"ASCII\" + :filters-alist ((:filter-headline . org-e-ascii-filter-headline-blank-lines) + \(:filter-section . org-e-ascii-filter-headline-blank-lines)) + :options-alist ((:ascii-charset nil nil org-e-ascii-charset)))" + (declare (debug (&define name sexp [&rest [keywordp sexp]] defbody)) + (indent 1)) + (let (filters options block-name) + (while (keywordp (car body)) + (case (pop body) + (:export-block (let ((names (pop body))) + (setq export-block + (if (consp names) (mapcar 'upcase names) + (list (upcase names)))))) + (:filters-alist (setq filters (pop body))) + (:options-alist (setq options (pop body))) + (t (pop body)))) + `(progn + ;; Define translators. + (defvar ,(intern (format "org-%s-translate-alist" backend)) ',translators + "Alist between element or object types and translators.") + ;; Define options. + ,(when options + `(defconst ,(intern (format "org-%s-options-alist" backend)) ',options + ,(format "Alist between %s export properties and ways to set them. +See `org-export-options-alist' for more information on the +structure of the values." + backend))) + ;; Define filters. + ,(when filters + `(defconst ,(intern (format "org-%s-filters-alist" backend)) ',filters + "Alist between filters keywords and back-end specific filters. +See `org-export-filters-alist' for more information.")) + ;; Tell parser to not parse EXPORT-BLOCK blocks. + ,(when export-block + `(mapc + (lambda (name) + (add-to-list 'org-element-block-name-alist + `(,name . org-element-export-block-parser))) + ',export-block)) + ;; Splice in the body, if any. + ,@body))) + (defmacro org-export-define-derived-backend (child parent &rest body) "Create a new back-end as a variant of an existing one. diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 469886308..37daa6ed9 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -538,7 +538,11 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01" ;; Standard test. (should (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX" - (org-element-map (org-element-parse-buffer) 'export-block 'identity))) + (org-element-map + (let ((org-element-block-name-alist + '(("LATEX" . org-element-export-block-parser)))) + (org-element-parse-buffer)) + 'export-block 'identity))) ;; Test folded block. (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX" (org-cycle) @@ -546,16 +550,26 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01" (org-element-property :hiddenp (org-element-map - (org-element-parse-buffer) 'export-block 'identity nil t)))) + (let ((org-element-block-name-alist + '(("LATEX" . org-element-export-block-parser)))) + (org-element-parse-buffer)) + 'export-block 'identity nil t)))) ;; Ignore case. (should (org-test-with-temp-text "#+begin_latex\nText\n#+end_latex" - (org-element-map (org-element-parse-buffer) 'export-block 'identity))) + (org-element-map + (let ((org-element-block-name-alist + '(("LATEX" . org-element-export-block-parser)))) + (org-element-parse-buffer)) + 'export-block 'identity))) ;; Ignore incomplete block. (should-not (org-test-with-temp-text "#+BEGIN_LATEX" (org-element-map - (org-element-parse-buffer) 'export-block 'identity nil t)))) + (let ((org-element-block-name-alist + '(("LATEX" . org-element-export-block-parser)))) + (org-element-parse-buffer)) + 'export-block 'identity nil t)))) ;;;; Export Snippet