Browse Source

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.
Nicolas Goaziou 12 years ago
parent
commit
6ea9d8c827

+ 58 - 67
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)))
 
 
 

+ 80 - 107
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)))
 
 
 

+ 59 - 64
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)))
 
 
 

+ 59 - 66
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.")
-
-(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.")
+(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)))
+
 
 ;;; Dependencies
 

+ 1 - 6
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))

+ 169 - 40
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.
 

+ 18 - 4
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