[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [O] [RFC] Changing internal representation of back-ends to defstruct
From: |
Carsten Dominik |
Subject: |
Re: [O] [RFC] Changing internal representation of back-ends to defstructs |
Date: |
Wed, 3 Jul 2013 23:48:54 +0200 |
Hi Nicolas,
this does look like a good change - and hopefully few enough external backends
have been written for this patch to not pose a problem.
- Carsten
On 3.7.2013, at 22:57, Nicolas Goaziou <address@hidden> wrote:
> Hello,
>
> Currently, a back-end is a symbol which may point to an entry in
> `org-export-registered-backends' variable. Therefore a back-end must be
> registered (with a unique name) before one can call it. Or, to put it
> differently, it is impossible to use an anonymous and temporary
> back-end.
>
> This is not satisfying for developers, as there are situations when you
> need to use a one-shot back-end but don't want to clutter registered
> back-ends list. You can of course let-bind
> `org-export-registered-backends' to something else, but it leads to
> clunky code. The process should be abstracted a bit more.
>
> The following (long) patches address this by defining back-ends as
> structures (see `defstruct'), possibly anonymous and by separating
> creation from registration process. It allows to quickly create and use
> temporary back-ends. In the example below, we quickly export a string
> using a temporary back-end:
>
> (org-export-string-as
> "* H1\n** H2\nSome string"
> (org-export-create-backend
> :transcoders
> '((headline . (lambda (h contents i)
> (let ((m (make-string (org-export-get-relative-level h i)
> ?=)))
> (concat m " " (org-element-property :raw-value h) " " m
> "\n"
> contents))))
> ;; Contents only.
> (section . (lambda (e c i) c))
> (paragraph . (lambda (e c i) c)))))
>
> It is also possible to create a temporary derived back-end. The
> following export will use registered `latex' back-end, excepted for
> `bold' type objects.
>
> (org-export-string-as
> "Some *bold* /string/"
> (org-export-create-backend
> :parent 'latex
> :transcoders '((italic . (lambda (o c i) (format "\\texit{%s}" c)))))
> 'body-only)
>
> Besides `org-export-create-backend', tools provided are:
> - `org-export-get-backend'
> - `org-export-register-backend'
> - `org-export-get-all-transcoders' (handles inheritance)
> - `org-export-get-all-options' (handles inheritance)
> - `org-export-get-all-filters' (handles inheritance)
>
> At a higher level, `org-export-define-backend' and
> `org-export-define-derived-backend' do not change (they are equivalent
> to create and register in a row). So this change only matters for
> back-end developers who used advanced features like
> `org-export-with-translations' (which should now be
> `org-export-with-backend' coupled with an anonymous back-end).
>
> Also, it leads to a cleaner implementation as it removes the confusion
> between a back-end and its name.
>
> The next step after applying this patch will be to make
> orgtbl-to-BACKEND functions use anonymous functions in order to
> support :splice property, which is tedious with the new export
> framework.
>
> Feedback welcome.
>
>
> Regards,
>
> --
> Nicolas Goaziou
> From 35bf951a1cd4c455f01863e128a899d36e76a76c Mon Sep 17 00:00:00 2001
> From: Nicolas Goaziou <address@hidden>
> Date: Mon, 24 Jun 2013 20:52:10 +0200
> Subject: [PATCH 1/2] ox: Change back-ends internal representation to
> structures
>
> * lisp/ox.el (org-export--registered-backends): Renamed from
> `org-export-registered-backends'.
> (org-export-invisible-backends): Removed variable.
> (org-export-get-backend, org-export-get-all-transcoders
> org-export-get-all-options, org-export-get-all-filters): New
> functions. It replaces `org-export-backend-translate-table'.
> (org-export-barf-if-invalid-backend, org-export-derived-backend-p,
> org-export-define-backend, org-export-define-derived-backend):
> Rewrite functions using new representation.
> (org-export-backend-translate-table): Remove function.
> (org-export-get-environment): Use new function.
> (org-export--get-subtree-options, org-export--parse-option-keyword,
> org-export--get-inbuffer-options, org-export--get-global-options,
> org-export-to-buffer org-export-to-file, org-export-string-as
> org-export-replace-region-by): Update docstring.
> (org-export-data-with-translations): Remove function. Use
> `org-export-data-with-backend' with a temporary back-end instead.
> (org-export-data-with-backend, org-export-as): Reflect new definition
> for back-ends.
> (org-export--dispatch-action, org-export--dispatch-ui): Reflect new
> definition for back-ends and variable removal. Refactoring.
> (org-export-filter-apply-functions): Call functions with
> current back-end's name, not full back-end.
> * lisp/org.el (org-export-backends, org-create-formula--latex-header):
> Use new structure and variables.
> * testing/lisp/test-ox.el: Update tests.
>
> This patch separates back-end definition from its registration. Thus,
> it allows to use anonymous or unregistered back-ends.
> ---
> lisp/org.el | 58 ++--
> lisp/ox.el | 527 +++++++++++++++++---------------
> testing/lisp/test-ox.el | 781 +++++++++++++++++++++++++++---------------------
> 3 files changed, 764 insertions(+), 602 deletions(-)
>
> diff --git a/lisp/org.el b/lisp/org.el
> index 6233972..89cc328 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -436,8 +436,9 @@ For export specific modules, see also
> `org-export-backends'."
> (const :tag "C wl: Links to Wanderlust
> folders/messages" org-wl)
> (repeat :tag "External packages" :inline t (symbol :tag "Package"))))
>
> -(defvar org-export-registered-backends) ; From ox.el
> +(defvar org-export--registered-backends) ; From ox.el.
> (declare-function org-export-derived-backend-p "ox" (backend &rest backends))
> +(declare-function org-export-backend-name "ox" (backend))
> (defcustom org-export-backends '(ascii html icalendar latex)
> "List of export back-ends that should be always available.
>
> @@ -451,30 +452,29 @@ needed.
>
> This variable needs to be set before org.el is loaded. If you
> need to make a change while Emacs is running, use the customize
> -interface or run the following code, where VALUE stands for the
> -new value of the variable, after updating it:
> +interface or run the following code, where VAL stands for the new
> +value of the variable, after updating it:
>
> \(progn
> - \(setq org-export-registered-backends
> + \(setq org-export--registered-backends
> \(org-remove-if-not
> \(lambda (backend)
> - \(or (memq backend val)
> - \(catch 'parentp
> - \(mapc
> - \(lambda (b)
> - \(and (org-export-derived-backend-p b (car backend))
> - \(throw 'parentp t)))
> - val)
> - nil)))
> - org-export-registered-backends))
> - \(let ((new-list (mapcar 'car org-export-registered-backends)))
> + \(let ((name (org-export-backend-name backend)))
> + \(or (memq name val)
> + \(catch 'parentp
> + \(dolist (b val)
> + \(and (org-export-derived-backend-p b name)
> + \(throw 'parentp t)))))))
> + org-export--registered-backends))
> + \(let ((new-list (mapcar 'org-export-backend-name
> + org-export--registered-backends)))
> \(dolist (backend val)
> \(cond
> \((not (load (format \"ox-%s\" backend) t t))
> \(message \"Problems while trying to load export back-end `%s'\"
> backend))
> \((not (memq backend new-list)) (push backend new-list))))
> - \(set-default var new-list)))
> + \(set-default 'org-export-backends new-list)))
>
> Adding a back-end to this list will also pull the back-end it
> depends on, if any."
> @@ -488,21 +488,20 @@ depends on, if any."
> ;; Any back-end not required anymore (not present in VAL and not
> ;; a parent of any back-end in the new value) is removed from the
> ;; list of registered back-ends.
> - (setq org-export-registered-backends
> + (setq org-export--registered-backends
> (org-remove-if-not
> (lambda (backend)
> - (or (memq backend val)
> - (catch 'parentp
> - (mapc
> - (lambda (b)
> - (and (org-export-derived-backend-p b (car backend))
> - (throw 'parentp t)))
> - val)
> - nil)))
> - org-export-registered-backends))
> + (let ((name (org-export-backend-name backend)))
> + (or (memq name val)
> + (catch 'parentp
> + (dolist (b val)
> + (and (org-export-derived-backend-p b name)
> + (throw 'parentp t)))))))
> + org-export--registered-backends))
> ;; Now build NEW-LIST of both new back-ends and required
> ;; parents.
> - (let ((new-list (mapcar 'car org-export-registered-backends)))
> + (let ((new-list (mapcar 'org-export-backend-name
> + org-export--registered-backends)))
> (dolist (backend val)
> (cond
> ((not (load (format "ox-%s" backend) t t))
> @@ -18494,14 +18493,17 @@ share a good deal of logic."
> "Invalid value of `org-latex-create-formula-image-program'")))
> string tofile options buffer))
>
> +(declare-function org-export-get-backend "ox" (name))
> (declare-function org-export--get-global-options "ox" (&optional backend))
> (declare-function org-export--get-inbuffer-options "ox" (&optional backend))
> (declare-function org-latex-guess-inputenc "ox-latex" (header))
> (declare-function org-latex-guess-babel-language "ox-latex" (header info))
> (defun org-create-formula--latex-header ()
> "Return LaTeX header appropriate for previewing a LaTeX snippet."
> - (let ((info (org-combine-plists (org-export--get-global-options 'latex)
> - (org-export--get-inbuffer-options 'latex))))
> + (let ((info (org-combine-plists (org-export--get-global-options
> + (org-export-get-backend 'latex))
> + (org-export--get-inbuffer-options
> + (org-export-get-backend 'latex)))))
> (org-latex-guess-babel-language
> (org-latex-guess-inputenc
> (org-splice-latex-header
> diff --git a/lisp/ox.el b/lisp/ox.el
> index 92ad356..71435b7 100644
> --- a/lisp/ox.el
> +++ b/lisp/ox.el
> @@ -47,15 +47,10 @@
> ;; The core function is `org-export-as'. It returns the transcoded
> ;; buffer as a string.
> ;;
> -;; An export back-end is defined with `org-export-define-backend',
> -;; which defines one mandatory information: his translation table.
> -;; 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.
> -;;
> -;; 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.
> +;; An export back-end is defined with `org-export-define-backend'.
> +;; This function can also support specific buffer keywords, OPTION
> +;; keyword's items and filters. Refer to function's 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
> @@ -280,14 +275,8 @@ containing the back-end used, as a symbol, and either a
> process
> or the time at which it finished. It is used to build the menu
> from `org-export-stack'.")
>
> -(defvar org-export-registered-backends nil
> +(defvar org-export--registered-backends nil
> "List of backends currently available in the exporter.
> -
> -A backend is stored as a list where CAR is its name, as a symbol,
> -and CDR is a plist with the following properties:
> -`:filters-alist', `:menu-entry', `:options-alist' and
> -`:translate-alist'.
> -
> This variable is set with `org-export-define-backend' and
> `org-export-define-derived-backend' functions.")
>
> @@ -830,20 +819,6 @@ process faster and the export more portable."
> :package-version '(Org . "8.0")
> :type '(file :must-match t))
>
> -(defcustom org-export-invisible-backends nil
> - "List of back-ends that shouldn't appear in the dispatcher.
> -
> -Any back-end belonging to this list or derived from a back-end
> -belonging to it will not appear in the dispatcher menu.
> -
> -Indeed, Org may require some export back-ends without notice. If
> -these modules are never to be used interactively, adding them
> -here will avoid cluttering the dispatcher menu."
> - :group 'org-export-general
> - :version "24.4"
> - :package-version '(Org . "8.0")
> - :type '(repeat (symbol :tag "Back-End")))
> -
> (defcustom org-export-dispatch-use-expert-ui nil
> "Non-nil means using a non-intrusive `org-export-dispatch'.
> In that case, no help buffer is displayed. Though, an indicator
> @@ -863,25 +838,147 @@ mode."
>
> ;;; Defining Back-ends
> ;;
> -;; `org-export-define-backend' is the standard way to define an export
> -;; back-end. It allows to specify translators, filters, buffer
> -;; options and a menu entry. If the new back-end shares translators
> -;; with another back-end, `org-export-define-derived-backend' may be
> -;; used instead.
> +;; An export back-end is a structure with `org-export-backend' type
> +;; and `name', `parent', `transcoders', `options', `filters', `blocks'
> +;; and `menu' slots.
> +;;
> +;; At the lowest level, a back-end is created with
> +;; `org-export-create-backend' function.
> +;;
> +;; A named back-end can be registered with
> +;; `org-export-register-backend' function. A registered back-end can
> +;; later be referred to by its name, with `org-export-get-backend'
> +;; function. Also, such a back-end can become the parent of a derived
> +;; back-end from which slot values will be inherited by default.
> +;; `org-export-derived-backend-p' can check if a given back-end is
> +;; derived from a list of back-end names.
> +;;
> +;; `org-export-get-all-transcoders', `org-export-get-all-options' and
> +;; `org-export-get-all-filters' return the full alist of transcoders,
> +;; options and filters, including those inherited from ancestors.
> ;;
> -;; Internally, a back-end is stored as a list, of which CAR is the
> -;; name of the back-end, as a symbol, and CDR a plist. Accessors to
> -;; properties of a given back-end are: `org-export-backend-filters',
> -;; `org-export-backend-menu', `org-export-backend-options' and
> -;; `org-export-backend-translate-table'.
> +;; At a higher level, `org-export-define-backend' is the standard way
> +;; to define an export back-end. If the new back-end is similar to
> +;; a registered back-end, `org-export-define-derived-backend' may be
> +;; used instead.
> ;;
> ;; Eventually `org-export-barf-if-invalid-backend' returns an error
> ;; when a given back-end hasn't been registered yet.
>
> -(defun org-export-define-backend (backend translators &rest body)
> +(defstruct (org-export-backend (:constructor org-export-create-backend)
> + (:copier nil))
> + name parent transcoders options filters blocks menu)
> +
> +(defun org-export-get-backend (name)
> + "Return export back-end named after NAME.
> +NAME is a symbol. Return nil if no such back-end is found."
> + (catch 'found
> + (dolist (b org-export--registered-backends)
> + (when (eq (org-export-backend-name b) name)
> + (throw 'found b)))))
> +
> +(defun org-export-register-backend (backend)
> + "Register BACKEND as a known export back-end.
> +BACKEND is a structure with `org-export-backend' type."
> + ;; Refuse to register an unnamed back-end.
> + (unless (org-export-backend-name backend)
> + (error "Cannot register a unnamed export back-end"))
> + ;; Refuse to register a back-end with an unknown parent.
> + (let ((parent (org-export-backend-parent backend)))
> + (when (and parent (not (org-export-get-backend parent)))
> + (error "Cannot use unknown \"%s\" back-end as a parent" parent)))
> + ;; Register dedicated export blocks in the parser.
> + (dolist (name (org-export-backend-blocks backend))
> + (add-to-list 'org-element-block-name-alist
> + (cons name 'org-element-export-block-parser)))
> + ;; If a back-end with the same name as BACKEND is already
> + ;; registered, replace it with BACKEND. Otherwise, simply add
> + ;; BACKEND to the list of registered back-ends.
> + (let ((old (org-export-get-backend (org-export-backend-name backend))))
> + (if old (setcar (memq old org-export--registered-backends) backend)
> + (push backend org-export--registered-backends))))
> +
> +(defun org-export-barf-if-invalid-backend (backend)
> + "Signal an error if BACKEND isn't defined."
> + (unless (org-export-backend-p backend)
> + (error "Unknown \"%s\" back-end: Aborting export" backend)))
> +
> +(defun org-export-derived-backend-p (backend &rest backends)
> + "Non-nil if BACKEND is derived from one of BACKENDS.
> +BACKEND is an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end. BACKENDS is constituted of symbols."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (when backend
> + (catch 'exit
> + (while (org-export-backend-parent backend)
> + (when (memq (org-export-backend-name backend) backends)
> + (throw 'exit t))
> + (setq backend
> + (org-export-get-backend (org-export-backend-parent backend))))
> + (memq (org-export-backend-name backend) backends))))
> +
> +(defun org-export-get-all-transcoders (backend)
> + "Return full translation table for BACKEND.
> +
> +BACKEND is an export back-end, as return by, e.g,,
> +`org-export-create-backend'. Return value is an alist where
> +keys are element or object types, as symbols, and values are
> +transcoders.
> +
> +Unlike to `org-export-backend-transcoders', this function
> +also returns transcoders inherited from parent back-ends,
> +if any."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (when backend
> + (let ((transcoders (org-export-backend-transcoders backend))
> + parent)
> + (while (setq parent (org-export-backend-parent backend))
> + (setq backend (org-export-get-backend parent))
> + (setq transcoders
> + (append transcoders (org-export-backend-transcoders backend))))
> + transcoders)))
> +
> +(defun org-export-get-all-options (backend)
> + "Return export options for BACKEND.
> +
> +BACKEND is an export back-end, as return by, e.g,,
> +`org-export-create-backend'. See `org-export-options-alist'
> +for the shape of the return value.
> +
> +Unlike to `org-export-backend-options', this function also
> +returns options inherited from parent back-ends, if any."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (when backend
> + (let ((options (org-export-backend-options backend))
> + parent)
> + (while (setq parent (org-export-backend-parent backend))
> + (setq backend (org-export-get-backend parent))
> + (setq options (append options (org-export-backend-options backend))))
> + options)))
> +
> +(defun org-export-get-all-filters (backend)
> + "Return complete list of filters for BACKEND.
> +
> +BACKEND is an export back-end, as return by, e.g,,
> +`org-export-create-backend'. Return value is an alist where
> +keys are symbols and values lists of functions.
> +
> +Unlike to `org-export-backend-filters', this function also
> +returns filters inherited from parent back-ends, if any."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (when backend
> + (let ((filters (org-export-backend-filters backend))
> + parent)
> + (while (setq parent (org-export-backend-parent backend))
> + (setq backend (org-export-get-backend parent))
> + (setq filters (append filters (org-export-backend-filters backend))))
> + filters)))
> +
> +(defun org-export-define-backend (backend transcoders &rest body)
> "Define a new back-end BACKEND.
>
> -TRANSLATORS is an alist between object or element types and
> +TRANSCODERS is an alist between object or element types and
> functions handling them.
>
> These functions should return a string without any trailing
> @@ -997,32 +1094,23 @@ keywords are understood:
> `org-export-options-alist' for more information about
> structure of the values."
> (declare (indent 1))
> - (let (export-block filters menu-entry options contents)
> + (let (blocks filters menu-entry options contents)
> (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))))))
> + (setq blocks (if (consp names) (mapcar 'upcase names)
> + (list (upcase names))))))
> (:filters-alist (setq filters (pop body)))
> (:menu-entry (setq menu-entry (pop body)))
> (:options-alist (setq options (pop body)))
> (t (pop body))))
> - (setq contents (append (list :translate-alist translators)
> - (and filters (list :filters-alist filters))
> - (and options (list :options-alist options))
> - (and menu-entry (list :menu-entry menu-entry))))
> - ;; Register back-end.
> - (let ((registeredp (assq backend org-export-registered-backends)))
> - (if registeredp (setcdr registeredp contents)
> - (push (cons backend contents) org-export-registered-backends)))
> - ;; 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))))
> + (org-export-register-backend
> + (org-export-create-backend :name backend
> + :transcoders transcoders
> + :options options
> + :filters filters
> + :blocks blocks
> + :menu menu-entry))))
>
> (defun org-export-define-derived-backend (child parent &rest body)
> "Create a new back-end as a variant of an existing one.
> @@ -1077,75 +1165,25 @@ The back-end could then be called with, for example:
>
> \(org-export-to-buffer 'my-latex \"*Test my-latex*\")"
> (declare (indent 2))
> - (let (export-block filters menu-entry options translators contents)
> + (let (blocks filters menu-entry options transcoders contents)
> (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))))))
> + (setq blocks (if (consp names) (mapcar 'upcase names)
> + (list (upcase names))))))
> (:filters-alist (setq filters (pop body)))
> (:menu-entry (setq menu-entry (pop body)))
> (:options-alist (setq options (pop body)))
> - (:translate-alist (setq translators (pop body)))
> + (:translate-alist (setq transcoders (pop body)))
> (t (pop body))))
> - (setq contents (append
> - (list :parent parent)
> - (let ((p-table (org-export-backend-translate-table parent)))
> - (list :translate-alist (append translators p-table)))
> - (let ((p-filters (org-export-backend-filters parent)))
> - (list :filters-alist (append filters p-filters)))
> - (let ((p-options (org-export-backend-options parent)))
> - (list :options-alist (append options p-options)))
> - (and menu-entry (list :menu-entry menu-entry))))
> - (org-export-barf-if-invalid-backend parent)
> - ;; Register back-end.
> - (let ((registeredp (assq child org-export-registered-backends)))
> - (if registeredp (setcdr registeredp contents)
> - (push (cons child contents) org-export-registered-backends)))
> - ;; 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))))
> -
> -(defun org-export-backend-parent (backend)
> - "Return back-end from which BACKEND is derived, or nil."
> - (plist-get (cdr (assq backend org-export-registered-backends)) :parent))
> -
> -(defun org-export-backend-filters (backend)
> - "Return filters for BACKEND."
> - (plist-get (cdr (assq backend org-export-registered-backends))
> - :filters-alist))
> -
> -(defun org-export-backend-menu (backend)
> - "Return menu entry for BACKEND."
> - (plist-get (cdr (assq backend org-export-registered-backends))
> - :menu-entry))
> -
> -(defun org-export-backend-options (backend)
> - "Return export options for BACKEND."
> - (plist-get (cdr (assq backend org-export-registered-backends))
> - :options-alist))
> -
> -(defun org-export-backend-translate-table (backend)
> - "Return translate table for BACKEND."
> - (plist-get (cdr (assq backend org-export-registered-backends))
> - :translate-alist))
> -
> -(defun org-export-barf-if-invalid-backend (backend)
> - "Signal an error if BACKEND isn't defined."
> - (unless (org-export-backend-translate-table backend)
> - (error "Unknown \"%s\" back-end: Aborting export" backend)))
> -
> -(defun org-export-derived-backend-p (backend &rest backends)
> - "Non-nil if BACKEND is derived from one of BACKENDS."
> - (let ((parent backend))
> - (while (and (not (memq parent backends))
> - (setq parent (org-export-backend-parent parent))))
> - parent))
> + (org-export-register-backend
> + (org-export-create-backend :name child
> + :parent parent
> + :transcoders transcoders
> + :options options
> + :filters filters
> + :blocks blocks
> + :menu menu-entry))))
>
>
>
> @@ -1448,14 +1486,15 @@ The back-end could then be called with, for example:
> ;; `org-export--get-subtree-options' and
> ;; `org-export--get-inbuffer-options'
> ;;
> -;; Also, `org-export--install-letbind-maybe' takes care of the part
> -;; relative to "#+BIND:" keywords.
> +;; Also, `org-export--list-bound-variables' collects bound variables
> +;; along with their value in order to set them as buffer local
> +;; variables later in the process.
>
> (defun org-export-get-environment (&optional backend subtreep ext-plist)
> "Collect export options from the current buffer.
>
> -Optional argument BACKEND is a symbol specifying which back-end
> -specific options to read, if any.
> +Optional argument BACKEND is an export back-end, as returned by
> +`org-export-create-backend'.
>
> When optional argument SUBTREEP is non-nil, assume the export is
> done against the current sub-tree.
> @@ -1481,8 +1520,7 @@ inferior to file-local settings."
> (list
> :back-end
> backend
> - :translate-alist
> - (org-export-backend-translate-table backend)
> + :translate-alist (org-export-get-all-transcoders backend)
> :footnote-definition-alist
> ;; Footnotes definitions must be collected in the original
> ;; buffer, as there's no insurance that they will still be in
> @@ -1518,11 +1556,12 @@ inferior to file-local settings."
>
> (defun org-export--parse-option-keyword (options &optional backend)
> "Parse an OPTIONS line and return values as a plist.
> -Optional argument BACKEND is a symbol specifying which back-end
> +Optional argument BACKEND is an export back-end, as returned by,
> +e.g., `org-export-create-backend'. It specifies which back-end
> specific items to read, if any."
> (let* ((all
> ;; Priority is given to back-end specific options.
> - (append (and backend (org-export-backend-options backend))
> + (append (and backend (org-export-get-all-options backend))
> org-export-options-alist))
> plist)
> (dolist (option all)
> @@ -1542,7 +1581,8 @@ specific items to read, if any."
>
> (defun org-export--get-subtree-options (&optional backend)
> "Get export options in subtree at point.
> -Optional argument BACKEND is a symbol specifying back-end used
> +Optional argument BACKEND is an export back-end, as returned by,
> +e.g., `org-export-create-backend'. It specifies back-end used
> for export. Return options as a plist."
> ;; For each buffer keyword, create a headline property setting the
> ;; same property in communication channel. The name for the property
> @@ -1594,7 +1634,7 @@ for export. Return options as a plist."
> (t value)))))))))
> ;; Look for both general keywords and back-end specific
> ;; options, with priority given to the latter.
> - (append (and backend (org-export-backend-options backend))
> + (append (and backend (org-export-get-all-options backend))
> org-export-options-alist)))
> ;; Return value.
> plist)))
> @@ -1602,7 +1642,8 @@ for export. Return options as a plist."
> (defun org-export--get-inbuffer-options (&optional backend)
> "Return current buffer export options, as a plist.
>
> -Optional argument BACKEND, when non-nil, is a symbol specifying
> +Optional argument BACKEND, when non-nil, is an export back-end,
> +as returned by, e.g., `org-export-create-backend'. It specifies
> which back-end specific options should also be read in the
> process.
>
> @@ -1612,7 +1653,7 @@ Assume buffer is in Org mode. Narrowing, if any, is
> ignored."
> (case-fold-search t)
> (options (append
> ;; Priority is given to back-end specific options.
> - (and backend (org-export-backend-options backend))
> + (and backend (org-export-get-all-options backend))
> org-export-options-alist))
> (regexp (format "^[ \t]*#\\+%s:"
> (regexp-opt (nconc (delq nil (mapcar 'cadr options))
> @@ -1725,12 +1766,13 @@ name."
>
> (defun org-export--get-global-options (&optional backend)
> "Return global export options as a plist.
> -Optional argument BACKEND, if non-nil, is a symbol specifying
> +Optional argument BACKEND, if non-nil, is an export back-end, as
> +returned by, e.g., `org-export-create-backend'. It specifies
> which back-end specific export options should also be read in the
> process."
> (let (plist
> ;; Priority is given to back-end specific options.
> - (all (append (and backend (org-export-backend-options backend))
> + (all (append (and backend (org-export-get-all-options backend))
> org-export-options-alist)))
> (dolist (cell all plist)
> (let ((prop (car cell)))
> @@ -2058,11 +2100,10 @@ a tree with a select tag."
> ;; back-end output. It takes care of filtering out elements or
> ;; objects according to export options and organizing the output blank
> ;; lines and white space are preserved. The function memoizes its
> -;; results, so it is cheap to call it within translators.
> +;; results, so it is cheap to call it within transcoders.
> ;;
> ;; It is possible to modify locally the back-end used by
> ;; `org-export-data' or even use a temporary back-end by using
> -;; `org-export-data-with-translations' and
> ;; `org-export-data-with-backend'.
> ;;
> ;; Internally, three functions handle the filtering of objects and
> @@ -2190,24 +2231,6 @@ Return transcoded string."
> results)))
> (plist-get info :exported-data))))))
>
> -(defun org-export-data-with-translations (data translations info)
> - "Convert DATA into another format using a given translation table.
> -DATA is an element, an object, a secondary string or a string.
> -TRANSLATIONS is an alist between element or object types and
> -a functions handling them. See `org-export-define-backend' for
> -more information. INFO is a plist used as a communication
> -channel."
> - (org-export-data
> - data
> - ;; Set-up a new communication channel with TRANSLATIONS as the
> - ;; translate table and a new hash table for memoization.
> - (org-combine-plists
> - info
> - (list :translate-alist translations
> - ;; Size of the hash table is reduced since this function
> - ;; will probably be used on short trees.
> - :exported-data (make-hash-table :test 'eq :size 401)))))
> -
> (defun org-export-data-with-backend (data backend info)
> "Convert DATA into BACKEND format.
>
> @@ -2217,9 +2240,18 @@ channel.
>
> Unlike to `org-export-with-backend', this function will
> recursively convert DATA using BACKEND translation table."
> - (org-export-barf-if-invalid-backend backend)
> - (org-export-data-with-translations
> - data (org-export-backend-translate-table backend) info))
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (org-export-data
> + data
> + ;; Set-up a new communication channel with translations defined in
> + ;; BACKEND as the translate table and a new hash table for
> + ;; memoization.
> + (org-combine-plists
> + info
> + (list :translate-alist (org-export-get-all-transcoders backend)
> + ;; Size of the hash table is reduced since this function
> + ;; will probably be used on short trees.
> + :exported-data (make-hash-table :test 'eq :size 401)))))
>
> (defun org-export--interpret-p (blob info)
> "Non-nil if element or object BLOB should be interpreted during export.
> @@ -2713,18 +2745,19 @@ channel, as a plist. It must return a string or
> nil.")
> "Call every function in FILTERS.
>
> Functions are called with arguments VALUE, current export
> -back-end and INFO. A function returning a nil value will be
> -skipped. If it returns the empty string, the process ends and
> +back-end's name and INFO. A function returning a nil value will
> +be skipped. If it returns the empty string, the process ends and
> VALUE is ignored.
>
> Call is done in a LIFO fashion, to be sure that developer
> specified filters, if any, are called first."
> (catch 'exit
> - (dolist (filter filters value)
> - (let ((result (funcall filter value (plist-get info :back-end) info)))
> - (cond ((not result) value)
> - ((equal value "") (throw 'exit nil))
> - (t (setq value result)))))))
> + (let ((backend-name (plist-get info :back-end)))
> + (dolist (filter filters value)
> + (let ((result (funcall filter value backend-name info)))
> + (cond ((not result) value)
> + ((equal value "") (throw 'exit nil))
> + (t (setq value result))))))))
>
> (defun org-export-install-filters (info)
> "Install filters properties in communication channel.
> @@ -2755,7 +2788,7 @@ Return the updated communication channel."
> plist key
> (if (atom value) (cons value (plist-get plist key))
> (append value (plist-get plist key))))))))
> - (org-export-backend-filters (plist-get info :back-end)))
> + (org-export-get-all-filters (plist-get info :back-end)))
> ;; Return new communication channel.
> (org-combine-plists info plist)))
>
> @@ -2891,6 +2924,10 @@ The function assumes BUFFER's major mode is
> `org-mode'."
> (backend &optional subtreep visible-only body-only ext-plist)
> "Transcode current Org buffer into BACKEND code.
>
> +BACKEND is either an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end.
> +
> If narrowing is active in the current buffer, only transcode its
> narrowed part.
>
> @@ -2911,6 +2948,7 @@ with external parameters overriding Org default
> settings, but
> still inferior to file-local settings.
>
> Return code as a string."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> (org-export-barf-if-invalid-backend backend)
> (save-excursion
> (save-restriction
> @@ -2943,8 +2981,9 @@ Return code as a string."
> ;; created, where include keywords, macros are expanded and
> ;; code blocks are evaluated.
> (org-export-with-buffer-copy
> - ;; Run first hook with current back-end as argument.
> - (run-hook-with-args 'org-export-before-processing-hook backend)
> + ;; Run first hook with current back-end's name as argument.
> + (run-hook-with-args 'org-export-before-processing-hook
> + (org-export-backend-name backend))
> (org-export-expand-include-keyword)
> ;; Update macro templates since #+INCLUDE keywords might have
> ;; added some new ones.
> @@ -2954,10 +2993,11 @@ Return code as a string."
> ;; Update radio targets since keyword inclusion might have
> ;; added some more.
> (org-update-radio-target-regexp)
> - ;; Run last hook with current back-end as argument.
> + ;; Run last hook with current back-end's name as argument.
> (goto-char (point-min))
> (save-excursion
> - (run-hook-with-args 'org-export-before-parsing-hook backend))
> + (run-hook-with-args 'org-export-before-parsing-hook
> + (org-export-backend-name backend)))
> ;; Update communication channel with environment. Also
> ;; install user's and developer's filters.
> (setq info
> @@ -2980,9 +3020,10 @@ Return code as a string."
> ;; Call options filters and update export options. We do not
> ;; use `org-export-filter-apply-functions' here since the
> ;; arity of such filters is different.
> - (dolist (filter (plist-get info :filter-options))
> - (let ((result (funcall filter info backend)))
> - (when result (setq info result))))
> + (let ((backend-name (org-export-backend-name backend)))
> + (dolist (filter (plist-get info :filter-options))
> + (let ((result (funcall filter info backend-name)))
> + (when result (setq info result)))))
> ;; Parse buffer and call parse-tree filter on it.
> (setq tree
> (org-export-filter-apply-functions
> @@ -3018,7 +3059,9 @@ Return code as a string."
> (backend buffer &optional subtreep visible-only body-only ext-plist)
> "Call `org-export-as' with output to a specified buffer.
>
> -BACKEND is the back-end used for transcoding, as a symbol.
> +BACKEND is either an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end.
>
> BUFFER is the output buffer. If it already exists, it will be
> erased first, otherwise, it will be created.
> @@ -3046,8 +3089,10 @@ to kill ring. Return buffer."
> (backend file &optional subtreep visible-only body-only ext-plist)
> "Call `org-export-as' with output to a specified file.
>
> -BACKEND is the back-end used for transcoding, as a symbol. FILE
> -is the name of the output file, as a string.
> +BACKEND is either an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end. FILE is the name of the output file, as
> +a string.
>
> Optional arguments SUBTREEP, VISIBLE-ONLY, BODY-ONLY and
> EXT-PLIST are similar to those used in `org-export-as', which
> @@ -3074,6 +3119,10 @@ to kill ring. Return output file's name."
> (defun org-export-string-as (string backend &optional body-only ext-plist)
> "Transcode STRING into BACKEND code.
>
> +BACKEND is either an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end.
> +
> When optional argument BODY-ONLY is non-nil, only return body
> code, without preamble nor postamble.
>
> @@ -3089,7 +3138,10 @@ Return code as a string."
>
> ;;;###autoload
> (defun org-export-replace-region-by (backend)
> - "Replace the active region by its export to BACKEND."
> + "Replace the active region by its export to BACKEND.
> +BACKEND is either an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end."
> (if (not (org-region-active-p))
> (user-error "No active region to replace")
> (let* ((beg (region-beginning))
> @@ -3103,10 +3155,10 @@ Return code as a string."
> (defun org-export-insert-default-template (&optional backend subtreep)
> "Insert all export keywords with default values at beginning of line.
>
> -BACKEND is a symbol representing the export back-end for which
> -specific export options should be added to the template, or
> -`default' for default template. When it is nil, the user will be
> -prompted for a category.
> +BACKEND is a symbol referring to the name of a registered export
> +back-end, for which specific export options should be added to
> +the template, or `default' for default template. When it is nil,
> +the user will be prompted for a category.
>
> If SUBTREEP is non-nil, export configuration will be set up
> locally for the subtree through node properties."
> @@ -3115,17 +3167,22 @@ locally for the subtree through node properties."
> (when (and subtreep (org-before-first-heading-p))
> (user-error "No subtree to set export options for"))
> (let ((node (and subtreep (save-excursion (org-back-to-heading t) (point))))
> - (backend (or backend
> - (intern
> - (org-completing-read
> - "Options category: "
> - (cons "default"
> - (mapcar (lambda (b) (symbol-name (car b)))
> - org-export-registered-backends))))))
> + (backend
> + (or backend
> + (intern
> + (org-completing-read
> + "Options category: "
> + (cons "default"
> + (mapcar (lambda (b)
> + (symbol-name (org-export-backend-name b)))
> + org-export--registered-backends))))))
> options keywords)
> ;; Populate OPTIONS and KEYWORDS.
> - (dolist (entry (if (eq backend 'default) org-export-options-alist
> - (org-export-backend-options backend)))
> + (dolist (entry (cond ((eq backend 'default) org-export-options-alist)
> + ((org-export-backend-p backend)
> + (org-export-get-all-options backend))
> + (t (org-export-get-all-options
> + (org-export-backend-name backend)))))
> (let ((keyword (nth 1 entry))
> (option (nth 2 entry)))
> (cond
> @@ -3502,16 +3559,20 @@ Caption lines are separated by a white space."
> ;; back-end, it may be used as a fall-back function once all specific
> ;; cases have been treated.
>
> -(defun org-export-with-backend (back-end data &optional contents info)
> - "Call a transcoder from BACK-END on DATA.
> -CONTENTS, when non-nil, is the transcoded contents of DATA
> -element, as a string. INFO, when non-nil, is the communication
> -channel used for export, as a plist.."
> - (org-export-barf-if-invalid-backend back-end)
> +(defun org-export-with-backend (backend data &optional contents info)
> + "Call a transcoder from BACKEND on DATA.
> +BACKEND is an export back-end, as returned by, e.g.,
> +`org-export-create-backend', or a symbol referring to
> +a registered back-end. DATA is an Org element, object, secondary
> +string or string. CONTENTS, when non-nil, is the transcoded
> +contents of DATA element, as a string. INFO, when non-nil, is
> +the communication channel used for export, as a plist."
> + (when (symbolp backend) (setq backend (org-export-get-backend backend)))
> + (org-export-barf-if-invalid-backend backend)
> (let ((type (org-element-type data)))
> (if (memq type '(nil org-data)) (error "No foreign transcoder available")
> (let ((transcoder
> - (cdr (assq type (org-export-backend-translate-table back-end)))))
> + (cdr (assq type (org-export-get-all-transcoders backend)))))
> (if (functionp transcoder) (funcall transcoder data contents info)
> (error "No foreign transcoder available"))))))
>
> @@ -5849,43 +5910,31 @@ back to standard interface."
> (lambda (value)
> ;; Fontify VALUE string.
> (org-propertize value 'face 'font-lock-variable-name-face)))
> - ;; Prepare menu entries by extracting them from
> - ;; `org-export-registered-backends', and sorting them by
> - ;; access key and by ordinal, if any.
> - (backends
> - (sort
> - (sort
> - (delq nil
> - (mapcar
> - (lambda (b)
> - (let ((name (car b)))
> - (catch 'ignored
> - ;; Ignore any back-end belonging to
> - ;; `org-export-invisible-backends' or derived
> - ;; from one of them.
> - (dolist (ignored org-export-invisible-backends)
> - (when (org-export-derived-backend-p name ignored)
> - (throw 'ignored nil)))
> - (org-export-backend-menu name))))
> - org-export-registered-backends))
> - (lambda (a b)
> - (let ((key-a (nth 1 a))
> - (key-b (nth 1 b)))
> - (cond ((and (numberp key-a) (numberp key-b))
> - (< key-a key-b))
> - ((numberp key-b) t)))))
> - (lambda (a b) (< (car a) (car b)))))
> + ;; Prepare menu entries by extracting them from registered
> + ;; back-ends and sorting them by access key and by ordinal,
> + ;; if any.
> + (entries
> + (sort (sort (delq nil
> + (mapcar 'org-export-backend-menu
> + org-export--registered-backends))
> + (lambda (a b)
> + (let ((key-a (nth 1 a))
> + (key-b (nth 1 b)))
> + (cond ((and (numberp key-a) (numberp key-b))
> + (< key-a key-b))
> + ((numberp key-b) t)))))
> + 'car-less-than-car))
> ;; Compute a list of allowed keys based on the first key
> ;; pressed, if any. Some keys
> ;; (?^B, ?^V, ?^S, ?^F, ?^A, ?&, ?# and ?q) are always
> ;; available.
> (allowed-keys
> (nconc (list 2 22 19 6 1)
> - (if (not first-key) (org-uniquify (mapcar 'car backends))
> + (if (not first-key) (org-uniquify (mapcar 'car entries))
> (let (sub-menu)
> - (dolist (backend backends (sort (mapcar 'car sub-menu) '<))
> - (when (eq (car backend) first-key)
> - (setq sub-menu (append (nth 2 backend) sub-menu))))))
> + (dolist (entry entries (sort (mapcar 'car sub-menu) '<))
> + (when (eq (car entry) first-key)
> + (setq sub-menu (append (nth 2 entry) sub-menu))))))
> (cond ((eq first-key ?P) (list ?f ?p ?x ?a))
> ((not first-key) (list ?P)))
> (list ?& ?#)
> @@ -5944,7 +5993,7 @@ back to standard interface."
> (nth 1 sub-entry)))
> sub-menu "")
> (when (zerop (mod index 2)) "\n"))))))))
> - backends ""))
> + entries ""))
> ;; Publishing menu is hard-coded.
> (format "\n[%s] Publish
> [%s] Current file [%s] Current project
> @@ -5979,7 +6028,7 @@ back to standard interface."
> ;; UI, display an intrusive help buffer.
> (if expertp
> (org-export--dispatch-action
> - expert-prompt allowed-keys backends options first-key expertp)
> + expert-prompt allowed-keys entries options first-key expertp)
> ;; At first call, create frame layout in order to display menu.
> (unless (get-buffer "*Org Export Dispatcher*")
> (delete-other-windows)
> @@ -6002,15 +6051,15 @@ back to standard interface."
> (set-window-start nil pos)))
> (org-fit-window-to-buffer)
> (org-export--dispatch-action
> - standard-prompt allowed-keys backends options first-key expertp))))
> + standard-prompt allowed-keys entries options first-key expertp))))
>
> (defun org-export--dispatch-action
> - (prompt allowed-keys backends options first-key expertp)
> + (prompt allowed-keys entries options first-key expertp)
> "Read a character from command input and act accordingly.
>
> PROMPT is the displayed prompt, as a string. ALLOWED-KEYS is
> a list of characters available at a given step in the process.
> -BACKENDS is a list of menu entries. OPTIONS, FIRST-KEY and
> +ENTRIES is a list of menu entries. OPTIONS, FIRST-KEY and
> EXPERTP are the same as defined in `org-export--dispatch-ui',
> which see.
>
> @@ -6067,9 +6116,9 @@ options as CDR."
> first-key expertp))
> ;; Action selected: Send key and options back to
> ;; `org-export-dispatch'.
> - ((or first-key (functionp (nth 2 (assq key backends))))
> + ((or first-key (functionp (nth 2 (assq key entries))))
> (cons (cond
> - ((not first-key) (nth 2 (assq key backends)))
> + ((not first-key) (nth 2 (assq key entries)))
> ;; Publishing actions are hard-coded. Send a special
> ;; signal to `org-export-dispatch'.
> ((eq first-key ?P)
> @@ -6082,10 +6131,10 @@ options as CDR."
> ;; path. Indeed, derived backends can share the same
> ;; FIRST-KEY.
> (t (catch 'found
> - (mapc (lambda (backend)
> - (let ((match (assq key (nth 2 backend))))
> + (mapc (lambda (entry)
> + (let ((match (assq key (nth 2 entry))))
> (when match (throw 'found (nth 2 match)))))
> - (member (assq first-key backends) backends)))))
> + (member (assq first-key entries) entries)))))
> options))
> ;; Otherwise, enter sub-menu.
> (t (org-export--dispatch-ui options key expertp)))))
> diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
> index cbae08a..0ba20f2 100644
> --- a/testing/lisp/test-ox.el
> +++ b/testing/lisp/test-ox.el
> @@ -24,30 +24,22 @@
> (unless (featurep 'ox)
> (signal 'missing-test-dependency "org-export"))
>
> -(defmacro org-test-with-backend (backend &rest body)
> - "Execute body with an export back-end defined.
> -
> -BACKEND is the name of the back-end. BODY is the body to
> -execute. The defined back-end simply returns parsed data as Org
> -syntax."
> - (declare (debug (form body)) (indent 1))
> - `(let ((org-export-registered-backends
> - ',(list
> - (list backend
> - :translate-alist
> - (let (transcode-table)
> - (dolist (type (append org-element-all-elements
> - org-element-all-objects)
> - transcode-table)
> - (push
> - (cons type
> - (lambda (obj contents info)
> - (funcall
> - (intern (format "org-element-%s-interpreter"
> - type))
> - obj contents)))
> - transcode-table)))))))
> - (progn ,@body)))
> +(defun org-test-default-backend ()
> + "Return a default export back-end.
> +This back-end simply returns parsed data as Org syntax."
> + (org-export-create-backend
> + :transcoders (let (transcode-table)
> + (dolist (type (append org-element-all-elements
> + org-element-all-objects)
> + transcode-table)
> + (push
> + (cons type
> + (lambda (obj contents info)
> + (funcall
> + (intern (format "org-element-%s-interpreter"
> + type))
> + obj contents)))
> + transcode-table)))))
>
> (defmacro org-test-with-parsed-data (data &rest body)
> "Execute body with parsed data available.
> @@ -108,12 +100,12 @@ already filled in `info'."
> (should
> (equal "Yes\n"
> (org-test-with-temp-text "#+BIND: test-ox-var value"
> - (let ((org-export-allow-bind-keywords t)
> - org-export-registered-backends)
> - (org-export-define-backend 'check
> + (let ((org-export-allow-bind-keywords t))
> + (org-export-as
> + (org-export-create-backend
> + :transcoders
> '((section . (lambda (s c i)
> - (if (eq test-ox-var 'value) "Yes" "No")))))
> - (org-export-as 'check))))))
> + (if (eq test-ox-var 'value) "Yes" "No")))))))))))
>
> (ert-deftest test-org-export/parse-option-keyword ()
> "Test reading all standard #+OPTIONS: items."
> @@ -276,14 +268,14 @@ Paragraph"
> 'equal
> (org-test-with-temp-text-in-file "Test"
> (org-mode)
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (text info)
> - (org-element-interpret-data
> - (plist-get info :title) info)))))
> - (list (org-export-as 'test)
> - (file-name-nondirectory
> - (file-name-sans-extension (buffer-file-name))))))))
> + (list (org-export-as
> + (org-export-create-backend
> + :transcoders
> + '((template . (lambda (text info)
> + (org-element-interpret-data
> + (plist-get info :title) info))))))
> + (file-name-nondirectory
> + (file-name-sans-extension (buffer-file-name)))))))
> ;; If no title is specified, and no file is associated to the
> ;; buffer, use buffer's name.
> (should
> @@ -291,36 +283,37 @@ Paragraph"
> 'equal
> (org-test-with-temp-text "Test"
> (org-mode)
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (text info)
> - (org-element-interpret-data
> - (plist-get info :title) info)))))
> - (list (org-export-as 'test) (buffer-name))))))
> + (list (org-export-as
> + (org-export-create-backend
> + :transcoders
> + '((template . (lambda (text info)
> + (org-element-interpret-data
> + (plist-get info :title) info))))))
> + (buffer-name)))))
> ;; If a title is specified, use it.
> (should
> (equal
> "Title"
> (org-test-with-temp-text-in-file "#+TITLE: Title\nTest"
> (org-mode)
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (text info)
> - (org-element-interpret-data
> - (plist-get info :title) info)))))
> - (org-export-as 'test)))))
> + (org-export-as
> + (org-export-create-backend
> + :transcoders
> + '((template . (lambda (text info)
> + (org-element-interpret-data
> + (plist-get info :title) info)))))))))
> ;; If an empty title is specified, do not set it.
> (should
> (equal
> ""
> (org-test-with-temp-text-in-file "#+TITLE:\nTest"
> (org-mode)
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (text info)
> - (org-element-interpret-data
> - (plist-get info :title) info)))))
> - (org-export-as 'test))))))
> + (org-export-as
> + (org-export-create-backend
> + :transcoders
> + '((template . (lambda (text info)
> + (org-element-interpret-data
> + (plist-get info :title) info))))))))))
>
> (ert-deftest test-org-export/handle-options ()
> "Test if export options have an impact on output."
> @@ -328,142 +321,148 @@ Paragraph"
> (should
> (equal ""
> (org-test-with-temp-text "* Head1 :noexp:"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:exclude-tags ("noexp")))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:exclude-tags ("noexp"))))))
> ;; Test include tags for headlines and inlinetasks.
> (should
> (equal "* H2\n** Sub :exp:\n*** Sub Sub\n"
> (org-test-with-temp-text "* H1\n* H2\n** Sub :exp:\n*** Sub Sub\n* H3"
> (let ((org-tags-column 0))
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:select-tags ("exp"))))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:select-tags ("exp")))))))
> ;; Test mixing include tags and exclude tags.
> - (org-test-with-temp-text "
> + (should
> + (string-match
> + "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n"
> + (org-test-with-temp-text "
> * Head1 :export:
> ** Sub-Head1 :noexport:
> ** Sub-Head2
> * Head2 :noexport:
> ** Sub-Head1 :export:"
> - (org-test-with-backend test
> - (should
> - (string-match
> - "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n"
> - (org-export-as
> - 'test nil nil nil
> - '(:select-tags ("export") :exclude-tags ("noexport")))))))
> + (org-export-as (org-test-default-backend) nil nil nil
> + '(:select-tags ("export") :exclude-tags ("noexport"))))))
> ;; Ignore tasks.
> (should
> (equal ""
> (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
> (org-test-with-temp-text "* TODO Head1"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-tasks nil)))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-tasks nil))))))
> (should
> (equal "* TODO Head1\n"
> (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
> (org-test-with-temp-text "* TODO Head1"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-tasks t)))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-tasks t))))))
> ;; Archived tree.
> - (org-test-with-temp-text "* Head1 :archive:"
> - (let ((org-archive-tag "archive"))
> - (org-test-with-backend test
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-archived-trees nil))
> - "")))))
> - (org-test-with-temp-text "* Head1 :archive:\nbody\n** Sub-head 2"
> - (let ((org-archive-tag "archive"))
> - (org-test-with-backend test
> - (should
> - (string-match
> - "\\* Head1[ \t]+:archive:"
> - (org-export-as 'test nil nil nil
> - '(:with-archived-trees headline)))))))
> - (org-test-with-temp-text "* Head1 :archive:"
> - (let ((org-archive-tag "archive"))
> - (org-test-with-backend test
> - (should
> - (string-match
> - "\\`\\* Head1[ \t]+:archive:\n\\'"
> - (org-export-as 'test nil nil nil '(:with-archived-trees t)))))))
> + (should
> + (equal ""
> + (org-test-with-temp-text "* Head1 :archive:"
> + (let ((org-archive-tag "archive"))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-archived-trees nil))))))
> + (should
> + (string-match
> + "\\* Head1[ \t]+:archive:"
> + (org-test-with-temp-text "* Head1 :archive:\nbody\n** Sub-head 2"
> + (let ((org-archive-tag "archive"))
> + (org-export-as (org-test-default-backend) nil nil nil
> + '(:with-archived-trees headline))))))
> + (should
> + (string-match
> + "\\`\\* Head1[ \t]+:archive:\n\\'"
> + (org-test-with-temp-text "* Head1 :archive:"
> + (let ((org-archive-tag "archive"))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-archived-trees t))))))
> ;; Clocks.
> - (let ((org-clock-string "CLOCK:"))
> - (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]"
> - (org-test-with-backend test
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-clocks t))
> - "CLOCK: [2012-04-29 sun. 10:45]\n"))
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-clocks nil)) "")))))
> + (should
> + (equal "CLOCK: [2012-04-29 sun. 10:45]\n"
> + (let ((org-clock-string "CLOCK:"))
> + (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-clocks t))))))
> + (should
> + (equal ""
> + (let ((org-clock-string "CLOCK:"))
> + (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-clocks nil))))))
> ;; Drawers.
> - (let ((org-drawers '("TEST")))
> - (org-test-with-temp-text ":TEST:\ncontents\n:END:"
> - (org-test-with-backend test
> - (should (equal (org-export-as 'test nil nil nil '(:with-drawers nil))
> - ""))
> - (should (equal (org-export-as 'test nil nil nil '(:with-drawers t))
> - ":TEST:\ncontents\n:END:\n")))))
> - (let ((org-drawers '("FOO" "BAR")))
> - (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
> - (org-test-with-backend test
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-drawers ("FOO")))
> - ":FOO:\nkeep\n:END:\n")))))
> - (let ((org-drawers '("FOO" "BAR")))
> - (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
> - (org-test-with-backend test
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-drawers (not "BAR")))
> - ":FOO:\nkeep\n:END:\n")))))
> + (should
> + (equal ""
> + (let ((org-drawers '("TEST")))
> + (org-test-with-temp-text ":TEST:\ncontents\n:END:"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-drawers nil))))))
> + (should
> + (equal ":TEST:\ncontents\n:END:\n"
> + (let ((org-drawers '("TEST")))
> + (org-test-with-temp-text ":TEST:\ncontents\n:END:"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-drawers t))))))
> + (should
> + (equal ":FOO:\nkeep\n:END:\n"
> + (let ((org-drawers '("FOO" "BAR")))
> + (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-drawers ("FOO")))))))
> + (should
> + (equal ":FOO:\nkeep\n:END:\n"
> + (let ((org-drawers '("FOO" "BAR")))
> + (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-drawers (not "BAR")))))))
> ;; Footnotes.
> (should
> (equal "Footnote?"
> (let ((org-footnote-section nil))
> (org-test-with-temp-text "Footnote?[fn:1]\n\n[fn:1] Def"
> - (org-test-with-backend test
> - (org-trim
> - (org-export-as 'test nil nil nil '(:with-footnotes nil))))))))
> + (org-trim (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-footnotes nil)))))))
> (should
> (equal "Footnote?[fn:1]\n\n[fn:1] Def"
> (let ((org-footnote-section nil))
> (org-test-with-temp-text "Footnote?[fn:1]\n\n[fn:1] Def"
> - (org-test-with-backend test
> - (org-trim
> - (org-export-as 'test nil nil nil '(:with-footnotes t))))))))
> + (org-trim (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-footnotes t)))))))
> ;; Inlinetasks.
> (when (featurep 'org-inlinetask)
> (should
> (equal
> + ""
> (let ((org-inlinetask-min-level 15))
> (org-test-with-temp-text "*************** Task"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-inlinetasks nil)))))
> - ""))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-inlinetasks nil))))))
> (should
> (equal
> + ""
> (let ((org-inlinetask-min-level 15))
> (org-test-with-temp-text
> "*************** Task\nContents\n*************** END"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-inlinetasks nil)))))
> - "")))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-inlinetasks nil)))))))
> ;; Plannings.
> - (let ((org-closed-string "CLOSED:"))
> - (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
> - (org-test-with-backend test
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-planning t))
> - "CLOSED: [2012-04-29 sun. 10:45]\n"))
> - (should
> - (equal (org-export-as 'test nil nil nil '(:with-planning nil))
> - "")))))
> + (should
> + (equal "CLOSED: [2012-04-29 sun. 10:45]\n"
> + (let ((org-closed-string "CLOSED:"))
> + (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-planning t))))))
> + (should
> + (equal ""
> + (let ((org-closed-string "CLOSED:"))
> + (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-planning nil))))))
> ;; Statistics cookies.
> (should
> (equal ""
> (org-test-with-temp-text "[0/0]"
> - (org-test-with-backend test
> - (org-export-as
> - 'test nil nil nil '(:with-statistics-cookies nil)))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-statistics-cookies nil))))))
>
> (ert-deftest test-org-export/with-timestamps ()
> "Test `org-export-with-timestamps' specifications."
> @@ -472,15 +471,15 @@ Paragraph"
> (equal
> "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>\n"
> (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-timestamps t))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-timestamps t)))))
> ;; nil value.
> (should
> (equal
> ""
> (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-timestamps nil))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-timestamps nil)))))
> ;; `active' value.
> (should
> (equal
> @@ -489,9 +488,8 @@ Paragraph"
> "<2012-03-29 Thu>[2012-03-29 Thu]
>
> Paragraph <2012-03-29 Thu>[2012-03-29 Thu]"
> - (org-test-with-backend test
> - (org-trim
> - (org-export-as 'test nil nil nil '(:with-timestamps active)))))))
> + (org-trim (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-timestamps active))))))
> ;; `inactive' value.
> (should
> (equal
> @@ -500,16 +498,16 @@ Paragraph <2012-03-29 Thu>[2012-03-29 Thu]"
> "<2012-03-29 Thu>[2012-03-29 Thu]
>
> Paragraph <2012-03-29 Thu>[2012-03-29 Thu]"
> - (org-test-with-backend test
> - (org-trim
> - (org-export-as 'test nil nil nil '(:with-timestamps inactive))))))))
> + (org-trim (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-timestamps inactive)))))))
>
> (ert-deftest test-org-export/comment-tree ()
> "Test if export process ignores commented trees."
> - (let ((org-comment-string "COMMENT"))
> - (org-test-with-temp-text "* COMMENT Head1"
> - (org-test-with-backend test
> - (should (equal (org-export-as 'test) ""))))))
> + (should
> + (equal ""
> + (let ((org-comment-string "COMMENT"))
> + (org-test-with-temp-text "* COMMENT Head1"
> + (org-export-as (org-test-default-backend)))))))
>
> (ert-deftest test-org-export/export-scope ()
> "Test all export scopes."
> @@ -518,22 +516,23 @@ Paragraph <2012-03-29 Thu>[2012-03-29 Thu]"
> ** Head2
> text
> *** Head3"
> - (org-test-with-backend test
> - ;; Subtree.
> - (forward-line 3)
> - (should (equal (org-export-as 'test 'subtree) "text\n*** Head3\n"))
> - ;; Visible.
> - (goto-char (point-min))
> - (forward-line)
> - (org-cycle)
> - (should (equal (org-export-as 'test nil 'visible) "* Head1\n"))
> - ;; Region.
> - (goto-char (point-min))
> - (forward-line 3)
> - (transient-mark-mode 1)
> - (push-mark (point) t t)
> - (goto-char (point-at-eol))
> - (should (equal (org-export-as 'test) "text\n"))))
> + ;; Subtree.
> + (forward-line 3)
> + (should (equal (org-export-as (org-test-default-backend) 'subtree)
> + "text\n*** Head3\n"))
> + ;; Visible.
> + (goto-char (point-min))
> + (forward-line)
> + (org-cycle)
> + (should (equal (org-export-as (org-test-default-backend) nil 'visible)
> + "* Head1\n"))
> + ;; Region.
> + (goto-char (point-min))
> + (forward-line 3)
> + (transient-mark-mode 1)
> + (push-mark (point) t t)
> + (goto-char (point-at-eol))
> + (should (equal (org-export-as (org-test-default-backend)) "text\n")))
> ;; Subtree with a code block calling another block outside.
> (should
> (equal ": 3\n"
> @@ -547,19 +546,18 @@ text
> #+BEGIN_SRC emacs-lisp
> \(+ 1 2)
> #+END_SRC"
> - (org-test-with-backend test
> - (forward-line 1)
> - (org-export-as 'test 'subtree)))))
> + (forward-line 1)
> + (org-export-as (org-test-default-backend) 'subtree))))
> ;; Body only.
> - (org-test-with-temp-text "Text"
> - (org-test-with-backend test
> - (plist-put
> - (cdr (assq 'test org-export-registered-backends))
> - :translate-alist
> - (cons (cons 'template (lambda (body info) (format "BEGIN\n%sEND"
> body)))
> - (org-export-backend-translate-table 'test)))
> - (should (equal (org-export-as 'test nil nil 'body-only) "Text\n"))
> - (should (equal (org-export-as 'test) "BEGIN\nText\nEND")))))
> + (let ((backend (org-test-default-backend)))
> + (setf (org-export-backend-transcoders backend)
> + (cons '(template . (lambda (body i)
> + (format "BEGIN\n%sEND" body)))
> + (org-export-backend-transcoders backend)))
> + (org-test-with-temp-text "Text"
> + (should (equal (org-export-as backend nil nil 'body-only)
> + "Text\n"))
> + (should (equal (org-export-as backend) "BEGIN\nText\nEND")))))
>
> (ert-deftest test-org-export/output-file-name ()
> "Test `org-export-output-file-name' specifications."
> @@ -667,7 +665,7 @@ body\n")))
> (should
> (equal "#+MACRO: macro1 value\nvalue\n"
> (org-test-with-temp-text "#+MACRO: macro1 value\n{{{macro1}}}"
> - (org-test-with-backend test (org-export-as 'test)))))
> + (org-export-as (org-test-default-backend)))))
> ;; Expand specific macros.
> (should
> (equal "me 2012-03-29 address@hidden Title\n"
> @@ -678,7 +676,7 @@ body\n")))
> #+AUTHOR: me
> #+EMAIL: address@hidden
> {{{author}}} {{{date}}} {{{email}}} {{{title}}}"
> - (let ((output (org-test-with-backend test (org-export-as 'test))))
> + (let ((output (org-export-as (org-test-default-backend))))
> (substring output (string-match ".*\n\\'" output))))))
> ;; Expand specific macros when property contained a regular macro
> ;; already.
> @@ -688,7 +686,7 @@ body\n")))
> #+MACRO: macro1 value
> #+TITLE: {{{macro1}}}
> {{{title}}}"
> - (let ((output (org-test-with-backend test (org-export-as 'test))))
> + (let ((output (org-export-as (org-test-default-backend))))
> (substring output (string-match ".*\n\\'" output))))))
> ;; Expand macros with templates in included files.
> (should
> @@ -696,57 +694,65 @@ body\n")))
> (org-test-with-temp-text
> (format "#+INCLUDE: \"%s/examples/macro-templates.org\"
> {{{included-macro}}}" org-test-dir)
> - (let ((output (org-test-with-backend test (org-export-as 'test))))
> + (let ((output (org-export-as (org-test-default-backend))))
> (substring output (string-match ".*\n\\'" output)))))))
>
> (ert-deftest test-org-export/user-ignore-list ()
> "Test if `:ignore-list' accepts user input."
> - (org-test-with-backend test
> - (flet ((skip-note-head
> - (data backend info)
> - ;; Ignore headlines with the word "note" in their title.
> - (org-element-map data 'headline
> - (lambda (headline)
> - (when (string-match "\\<note\\>"
> - (org-element-property :raw-value headline))
> - (org-export-ignore-element headline info)))
> - info)
> - data))
> - ;; Install function in parse tree filters.
> - (let ((org-export-filter-parse-tree-functions '(skip-note-head)))
> - (org-test-with-temp-text "* Head1\n* Head2 (note)\n"
> - (should (equal (org-export-as 'test) "* Head1\n")))))))
> + (let ((backend (org-test-default-backend)))
> + (setf (org-export-backend-transcoders backend)
> + (cons '(template . (lambda (body i)
> + (format "BEGIN\n%sEND" body)))
> + (org-export-backend-transcoders backend)))
> + (org-test-with-temp-text "Text"
> + (should (equal (org-export-as backend nil nil 'body-only)
> + "Text\n"))
> + (should (equal (org-export-as backend) "BEGIN\nText\nEND"))))
> + (should
> + (equal
> + "* Head1\n"
> + (let ((org-export-filter-parse-tree-functions
> + '((lambda (data backend info)
> + ;; Ignore headlines with the word "note" in their title.
> + (org-element-map data 'headline
> + (lambda (headline)
> + (when (string-match "\\<note\\>"
> + (org-element-property :raw-value
> + headline))
> + (org-export-ignore-element headline info)))
> + info)
> + data))))
> + (org-test-with-temp-text "* Head1\n* Head2 (note)\n"
> + (org-export-as (org-test-default-backend)))))))
>
> (ert-deftest test-org-export/before-processing-hook ()
> "Test `org-export-before-processing-hook'."
> (should
> (equal
> "#+MACRO: mac val\nTest\n"
> - (org-test-with-backend test
> - (org-test-with-temp-text "#+MACRO: mac val\n{{{mac}}} Test"
> - (let ((org-export-before-processing-hook
> - '((lambda (backend)
> - (while (re-search-forward "{{{" nil t)
> - (let ((object (org-element-context)))
> - (when (eq (org-element-type object) 'macro)
> - (delete-region
> - (org-element-property :begin object)
> - (org-element-property :end object)))))))))
> - (org-export-as 'test)))))))
> + (org-test-with-temp-text "#+MACRO: mac val\n{{{mac}}} Test"
> + (let ((org-export-before-processing-hook
> + '((lambda (backend)
> + (while (re-search-forward "{{{" nil t)
> + (let ((object (org-element-context)))
> + (when (eq (org-element-type object) 'macro)
> + (delete-region
> + (org-element-property :begin object)
> + (org-element-property :end object)))))))))
> + (org-export-as (org-test-default-backend)))))))
>
> (ert-deftest test-org-export/before-parsing-hook ()
> "Test `org-export-before-parsing-hook'."
> (should
> (equal "Body 1\nBody 2\n"
> - (org-test-with-backend test
> - (org-test-with-temp-text "* Headline 1\nBody 1\n* Headline 2\nBody
> 2"
> - (let ((org-export-before-parsing-hook
> - '((lambda (backend)
> - (goto-char (point-min))
> - (while (re-search-forward org-outline-regexp-bol nil t)
> - (delete-region
> - (point-at-bol) (progn (forward-line) (point))))))))
> - (org-export-as 'test)))))))
> + (org-test-with-temp-text "* Headline 1\nBody 1\n* Headline 2\nBody 2"
> + (let ((org-export-before-parsing-hook
> + '((lambda (backend)
> + (goto-char (point-min))
> + (while (re-search-forward org-outline-regexp-bol nil t)
> + (delete-region
> + (point-at-bol) (progn (forward-line) (point))))))))
> + (org-export-as (org-test-default-backend)))))))
>
>
>
> @@ -833,37 +839,37 @@ body\n")))
> ;; Translate table.
> (should
> (equal '((headline . my-headline-test))
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . my-headline-test)))
> - (org-export-backend-translate-table 'test))))
> + (org-export-get-all-transcoders 'test))))
> ;; Filters.
> (should
> (equal '((:filter-headline . my-filter))
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test
> '((headline . my-headline-test))
> :filters-alist '((:filter-headline . my-filter)))
> - (org-export-backend-filters 'test))))
> + (org-export-backend-filters (org-export-get-backend 'test)))))
> ;; Options.
> (should
> (equal '((:prop value))
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test
> '((headline . my-headline-test))
> :options-alist '((:prop value)))
> - (org-export-backend-options 'test))))
> + (org-export-backend-options (org-export-get-backend 'test)))))
> ;; Menu.
> (should
> (equal '(?k "Test Export" test)
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test
> '((headline . my-headline-test))
> :menu-entry '(?k "Test Export" test))
> - (org-export-backend-menu 'test))))
> + (org-export-backend-menu (org-export-get-backend 'test)))))
> ;; Export Blocks.
> (should
> (equal '(("TEST" . org-element-export-block-parser))
> - (let (org-export-registered-backends org-element-block-name-alist)
> + (let (org-export--registered-backends org-element-block-name-alist)
> (org-export-define-backend 'test
> '((headline . my-headline-test))
> :export-block '("test"))
> @@ -873,115 +879,218 @@ body\n")))
> "Test `org-export-define-derived-backend' specifications."
> ;; Error when parent back-end is not defined.
> (should-error
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-derived-backend 'test 'parent)))
> ;; Append translation table to parent's.
> (should
> (equal '((:headline . test) (:headline . parent))
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'parent '((:headline . parent)))
> (org-export-define-derived-backend 'test 'parent
> :translate-alist '((:headline . test)))
> - (org-export-backend-translate-table 'test))))
> + (org-export-get-all-transcoders 'test))))
> ;; Options defined in the new back have priority over those defined
> ;; in parent.
> (should
> (eq 'test
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'parent
> '((:headline . parent))
> :options-alist '((:a nil nil 'parent)))
> (org-export-define-derived-backend 'test 'parent
> :options-alist '((:a nil nil 'test)))
> - (plist-get (org-export--get-global-options 'test) :a)))))
> + (plist-get (org-export--get-global-options
> + (org-export-get-backend 'test))
> + :a)))))
>
> (ert-deftest test-org-export/derived-backend-p ()
> "Test `org-export-derived-backend-p' specifications."
> ;; Non-nil with direct match.
> (should
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-derived-backend-p 'test 'test)))
> (should
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-define-derived-backend 'test2 'test)
> (org-export-derived-backend-p 'test2 'test2)))
> ;; Non-nil with a direct parent.
> (should
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-define-derived-backend 'test2 'test)
> (org-export-derived-backend-p 'test2 'test)))
> ;; Non-nil with an indirect parent.
> (should
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-define-derived-backend 'test2 'test)
> (org-export-define-derived-backend 'test3 'test2)
> (org-export-derived-backend-p 'test3 'test)))
> ;; Nil otherwise.
> (should-not
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-define-backend 'test2 '((headline . test2)))
> (org-export-derived-backend-p 'test2 'test)))
> (should-not
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test '((headline . test)))
> (org-export-define-backend 'test2 '((headline . test2)))
> (org-export-define-derived-backend 'test3 'test2)
> (org-export-derived-backend-p 'test3 'test))))
>
> +(ert-deftest test-org-export/get-all-transcoders ()
> + "Test `org-export-get-all-transcoders' specifications."
> + ;; Return nil when back-end cannot be found.
> + (should-not (org-export-get-all-transcoders nil))
> + ;; Same as `org-export-transcoders' if no parent.
> + (should
> + (equal '((headline . ignore))
> + (org-export-get-all-transcoders
> + (org-export-create-backend
> + :transcoders '((headline . ignore))))))
> + ;; But inherit from all ancestors whenever possible.
> + (should
> + (equal '((section . ignore) (headline . ignore))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 '((headline . ignore)))
> + (org-export-get-all-transcoders
> + (org-export-create-backend
> + :parent 'b1 :transcoders '((section . ignore)))))))
> + (should
> + (equal '((paragraph . ignore) (section . ignore) (headline . ignore))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 '((headline . ignore)))
> + (org-export-define-derived-backend 'b2 'b1
> + :translate-alist '((section . ignore)))
> + (org-export-get-all-transcoders
> + (org-export-create-backend
> + :parent 'b2 :transcoders '((paragraph . ignore)))))))
> + ;; Back-end transcoders overrule inherited ones.
> + (should
> + (eq 'b
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 '((headline . a)))
> + (cdr (assq 'headline
> + (org-export-get-all-transcoders
> + (org-export-create-backend
> + :parent 'b1 :transcoders '((headline . b))))))))))
> +
> +(ert-deftest test-org-export/get-all-options ()
> + "Test `org-export-get-all-options' specifications."
> + ;; Return nil when back-end cannot be found.
> + (should-not (org-export-get-all-options nil))
> + ;; Same as `org-export-options' if no parent.
> + (should
> + (equal '((headline . ignore))
> + (org-export-get-all-options
> + (org-export-create-backend
> + :options '((headline . ignore))))))
> + ;; But inherit from all ancestors whenever possible.
> + (should
> + (equal '((:key2 value2) (:key1 value1))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 nil :options-alist '((:key1 value1)))
> + (org-export-get-all-options
> + (org-export-create-backend
> + :parent 'b1 :options '((:key2 value2)))))))
> + (should
> + (equal '((:key3 value3) (:key2 value2) (:key1 value1))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 nil :options-alist '((:key1 value1)))
> + (org-export-define-derived-backend 'b2 'b1
> + :options-alist '((:key2 value2)))
> + (org-export-get-all-options
> + (org-export-create-backend
> + :parent 'b2 :options '((:key3 value3)))))))
> + ;; Back-end options overrule inherited ones.
> + (should
> + (eq 'b
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 nil :options-alist '((:key1 . a)))
> + (cdr (assq :key1
> + (org-export-get-all-options
> + (org-export-create-backend
> + :parent 'b1 :options '((:key1 . b))))))))))
> +
> +(ert-deftest test-org-export/get-all-filters ()
> + "Test `org-export-get-all-filters' specifications."
> + ;; Return nil when back-end cannot be found.
> + (should-not (org-export-get-all-filters nil))
> + ;; Same as `org-export-filters' if no parent.
> + (should
> + (equal '((:filter-headline . ignore))
> + (org-export-get-all-filters
> + (org-export-create-backend
> + :filters '((:filter-headline . ignore))))))
> + ;; But inherit from all ancestors whenever possible.
> + (should
> + (equal '((:filter-section . ignore) (:filter-headline . ignore))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1
> + nil :filters-alist '((:filter-headline . ignore)))
> + (org-export-get-all-filters
> + (org-export-create-backend
> + :parent 'b1 :filters '((:filter-section . ignore)))))))
> + (should
> + (equal '((:filter-paragraph . ignore)
> + (:filter-section . ignore)
> + (:filter-headline . ignore))
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1
> + nil :filters-alist '((:filter-headline . ignore)))
> + (org-export-define-derived-backend 'b2 'b1
> + :filters-alist '((:filter-section . ignore)))
> + (org-export-get-all-filters
> + (org-export-create-backend
> + :parent 'b2 :filters '((:filter-paragraph . ignore)))))))
> + ;; Back-end filters overrule inherited ones.
> + (should
> + (eq 'b
> + (let (org-export--registered-backends)
> + (org-export-define-backend 'b1 '((:filter-headline . a)))
> + (cdr (assq :filter-headline
> + (org-export-get-all-filters
> + (org-export-create-backend
> + :parent 'b1 :filters '((:filter-headline . b))))))))))
> +
> (ert-deftest test-org-export/with-backend ()
> "Test `org-export-with-backend' definition."
> ;; Error when calling an undefined back-end
> - (should-error
> - (let (org-export-registered-backends)
> - (org-export-with-backend 'test "Test")))
> + (should-error (org-export-with-backend nil "Test"))
> ;; Error when called back-end doesn't have an appropriate
> ;; transcoder.
> (should-error
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test ((headline . ignore)))
> - (org-export-with-backend 'test "Test")))
> + (org-export-with-backend
> + (org-export-create-backend :transcoders '((headline . ignore)))
> + "Test"))
> ;; Otherwise, export using correct transcoder
> (should
> (equal "Success"
> - (let (org-export-registered-backends)
> + (let (org-export--registered-backends)
> (org-export-define-backend 'test
> '((plain-text . (lambda (text contents info) "Failure"))))
> (org-export-define-backend 'test2
> '((plain-text . (lambda (text contents info) "Success"))))
> (org-export-with-backend 'test2 "Test")))))
>
> -(ert-deftest test-org-export/data-with-translations ()
> - "Test `org-export-data-with-translations' specifications."
> - (should
> - (equal
> - "Success!"
> - (org-export-data-with-translations
> - '(bold nil "Test")
> - '((plain-text . (lambda (text info) "Success"))
> - (bold . (lambda (bold contents info) (concat contents "!"))))
> - '(:with-emphasize t)))))
> -
> (ert-deftest test-org-export/data-with-backend ()
> "Test `org-export-data-with-backend' specifications."
> ;; Error when calling an undefined back-end.
> - (should-error
> - (let (org-export-registered-backends)
> - (org-export-data-with-backend 'test "Test" nil)))
> + (should-error (org-export-data-with-backend nil "nil" nil))
> ;; Otherwise, export data recursively, using correct back-end.
> (should
> (equal
> "Success!"
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((plain-text . (lambda (text info) "Success"))
> - (bold . (lambda (bold contents info) (concat contents "!")))))
> - (org-export-data-with-backend
> - '(bold nil "Test") 'test '(:with-emphasize t))))))
> + (org-export-data-with-backend
> + '(bold nil "Test")
> + (org-export-create-backend
> + :transcoders
> + '((plain-text . (lambda (text info) "Success"))
> + (bold . (lambda (bold contents info) (concat contents "!")))))
> + '(:with-emphasize t)))))
>
>
>
> @@ -989,28 +1098,30 @@ body\n")))
>
> (ert-deftest test-org-export/export-snippet ()
> "Test export snippets transcoding."
> + ;; Standard test.
> (org-test-with-temp-text "@@test:A@@@@t:B@@"
> - (org-test-with-backend test
> - (plist-put
> - (cdr (assq 'test org-export-registered-backends))
> - :translate-alist
> - (cons (cons 'export-snippet
> - (lambda (snippet contents info)
> - (when (eq (org-export-snippet-backend snippet) 'test)
> - (org-element-property :value snippet))))
> - (org-export-backend-translate-table 'test)))
> + (let ((backend (org-test-default-backend)))
> + (setf (org-export-backend-name backend) 'test)
> + (setf (org-export-backend-transcoders backend)
> + (cons (cons 'export-snippet
> + (lambda (snippet contents info)
> + (when (eq (org-export-snippet-backend snippet) 'test)
> + (org-element-property :value snippet))))
> + (org-export-backend-transcoders backend)))
> (let ((org-export-snippet-translation-alist nil))
> - (should (equal (org-export-as 'test) "A\n")))
> + (should (equal (org-export-as backend) "A\n")))
> (let ((org-export-snippet-translation-alist '(("t" . "test"))))
> - (should (equal (org-export-as 'test) "AB\n")))))
> + (should (equal (org-export-as backend) "AB\n")))))
> ;; Ignored export snippets do not remove any blank.
> (should
> (equal "begin end\n"
> (org-test-with-parsed-data "begin @@test:A@@ end"
> - (org-export-data-with-translations
> + (org-export-data-with-backend
> tree
> - '((paragraph . (lambda (paragraph contents info) contents))
> - (section . (lambda (section contents info) contents)))
> + (org-export-create-backend
> + :transcoders
> + '((paragraph . (lambda (paragraph contents info) contents))
> + (section . (lambda (section contents info) contents))))
> info)))))
>
>
> @@ -1036,11 +1147,11 @@ body\n")))
> (car (org-element-contents def))))))))
> info))))
> ;; 2. Test nested footnotes order.
> - (org-test-with-parsed-data
> - "Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
> - (should
> - (equal
> - '((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
> + (should
> + (equal
> + '((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
> + (org-test-with-parsed-data
> + "Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
> (org-element-map tree 'footnote-reference
> (lambda (ref)
> (when (org-export-footnote-first-reference-p ref info)
> @@ -1060,29 +1171,30 @@ body\n")))
> (should
> (= (length (org-export-collect-footnote-definitions tree info)) 2))))
> ;; 4. Test footnotes definitions collection.
> - (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3].
> + (should
> + (= 4
> + (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3].
>
> \[fn:2] B [fn:3] [fn::D].
>
> \[fn:3] C."
> - (should (= (length (org-export-collect-footnote-definitions tree info))
> - 4)))
> + (length (org-export-collect-footnote-definitions tree info)))))
> ;; 5. Test export of footnotes defined outside parsing scope.
> - (org-test-with-temp-text "[fn:1] Out of scope
> + (should
> + (equal
> + "ParagraphOut of scope\n"
> + (org-test-with-temp-text "[fn:1] Out of scope
> * Title
> Paragraph[fn:1]"
> - (org-test-with-backend test
> - (plist-put
> - (cdr (assq 'test org-export-registered-backends))
> - :translate-alist
> - (cons (cons 'footnote-reference
> - (lambda (fn contents info)
> - (org-element-interpret-data
> - (org-export-get-footnote-definition fn info))))
> - (org-export-backend-translate-table 'test)))
> - (forward-line)
> - (should (equal "ParagraphOut of scope\n"
> - (org-export-as 'test 'subtree)))))
> + (let ((backend (org-test-default-backend)))
> + (setf (org-export-backend-transcoders backend)
> + (cons (cons 'footnote-reference
> + (lambda (fn contents info)
> + (org-element-interpret-data
> + (org-export-get-footnote-definition fn info))))
> + (org-export-backend-transcoders backend)))
> + (forward-line)
> + (org-export-as backend 'subtree)))))
> ;; 6. Footnotes without a definition should be provided a fallback
> ;; definition.
> (should
> @@ -1378,8 +1490,8 @@ Paragraph[fn:1]"
> ""
> (let ((org-inlinetask-min-level 3))
> (org-test-with-temp-text "*** Inlinetask :noexp:\nContents\n*** end"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:exclude-tags ("noexp"))))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:exclude-tags ("noexp")))))))
> ;; Inlinetask with an include tag.
> (should
> (equal
> @@ -1387,16 +1499,16 @@ Paragraph[fn:1]"
> (let ((org-inlinetask-min-level 3)
> (org-tags-column 0))
> (org-test-with-temp-text "* H1\n* H2\n*** Inline :exp:"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:select-tags ("exp"))))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:select-tags ("exp")))))))
> ;; Ignore inlinetask with a TODO keyword and tasks excluded.
> (should
> (equal ""
> (let ((org-todo-keywords '((sequence "TODO" "DONE")))
> (org-inlinetask-min-level 3))
> (org-test-with-temp-text "*** TODO Inline"
> - (org-test-with-backend test
> - (org-export-as 'test nil nil nil '(:with-tasks nil)))))))))
> + (org-export-as (org-test-default-backend)
> + nil nil nil '(:with-tasks nil))))))))
>
>
>
> @@ -2492,41 +2604,40 @@ Another text. (ref:text)
> "Test `inner-template' translator specifications."
> (should
> (equal "Success!"
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> + (org-test-with-temp-text "* Headline"
> + (org-export-as
> + (org-export-create-backend
> + :transcoders
> '((inner-template . (lambda (contents info) "Success!"))
> - (headline . (lambda (h c i) "Headline"))))
> - (org-test-with-temp-text "* Headline"
> - (org-export-as 'test)))))
> + (headline . (lambda (h c i) "Headline"))))))))
> ;; Inner template is applied even in a "body-only" export.
> (should
> (equal "Success!"
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((inner-template . (lambda (contents info) "Success!"))
> - (headline . (lambda (h c i) "Headline"))))
> - (org-test-with-temp-text "* Headline"
> - (org-export-as 'test nil nil 'body-only))))))
> + (org-test-with-temp-text "* Headline"
> + (org-export-as
> + (org-export-create-backend
> + :transcoders '((inner-template . (lambda (c i) "Success!"))
> + (headline . (lambda (h c i) "Headline"))))
> + nil nil 'body-only)))))
>
> (ert-deftest test-org-export/template ()
> "Test `template' translator specifications."
> (should
> (equal "Success!"
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (contents info) "Success!"))
> - (headline . (lambda (h c i) "Headline"))))
> - (org-test-with-temp-text "* Headline"
> - (org-export-as 'test)))))
> + (org-test-with-temp-text "* Headline"
> + (org-export-as
> + (org-export-create-backend
> + :transcoders '((template . (lambda (contents info) "Success!"))
> + (headline . (lambda (h c i) "Headline"))))))))
> ;; Template is not applied in a "body-only" export.
> (should-not
> (equal "Success!"
> - (let (org-export-registered-backends)
> - (org-export-define-backend 'test
> - '((template . (lambda (contents info) "Success!"))
> - (headline . (lambda (h c i) "Headline"))))
> - (org-test-with-temp-text "* Headline"
> - (org-export-as 'test nil nil 'body-only))))))
> + (org-test-with-temp-text "* Headline"
> + (org-export-as
> + (org-export-create-backend
> + :transcoders '((template . (lambda (contents info) "Success!"))
> + (headline . (lambda (h c i) "Headline"))))
> + nil nil 'body-only)))))
>
>
>
> --
> 1.8.3.2
>
> From 5c3b1765d219fc55edac393460128b9cd8d0d013 Mon Sep 17 00:00:00 2001
> From: Nicolas Goaziou <address@hidden>
> Date: Mon, 24 Jun 2013 20:55:24 +0200
> Subject: [PATCH 2/2] Export back-ends: Apply changes to back-end structure
>
> * lisp/ox-html.el (org-html--format-toc-headline): Make use of
> anonymous back-ends.
> * lisp/ox-odt.el (org-odt-footnote-reference): Make use of anonymous
> back-ends.
> (org-odt-format-label, org-odt-toc, org-odt-format-headline--wrap):
> Use `org-export-with-backend' instead of
> `org-export-with-translations'.
> * contrib/lisp/ox-freemind.el (org-freemind--build-node-contents): Use
> `org-export-with-backend' instead of `org-export-with-translations'.
> ---
> contrib/lisp/ox-freemind.el | 11 +++---
> lisp/ox-html.el | 19 ++++++-----
> lisp/ox-odt.el | 83 +++++++++++++++++++++++----------------------
> 3 files changed, 57 insertions(+), 56 deletions(-)
>
> diff --git a/contrib/lisp/ox-freemind.el b/contrib/lisp/ox-freemind.el
> index 4e90eff..d31c65f 100644
> --- a/contrib/lisp/ox-freemind.el
> +++ b/contrib/lisp/ox-freemind.el
> @@ -316,12 +316,11 @@ will result in following node:
> (element-contents (org-element-contents element))
> (section (assoc 'section element-contents))
> (section-contents
> - (let* ((translations
> - (nconc (list (cons 'section
> - (lambda (section contents info)
> - contents)))
> - (plist-get info :translate-alist))))
> - (org-export-data-with-translations section translations info)))
> + (let ((backend (org-export-create-backend
> + :parent (org-export-backend-name
> + (plist-get info :back-end))
> + :translations '(section . (lambda (e c i) c)))))
> + (org-export-data-with-backend section backend info)))
> (itemized-contents-p (let ((first-child-headline
> (org-element-map element-contents
> 'headline 'identity info t)))
> diff --git a/lisp/ox-html.el b/lisp/ox-html.el
> index 9ce73c4..0c997b4 100644
> --- a/lisp/ox-html.el
> +++ b/lisp/ox-html.el
> @@ -1983,16 +1983,17 @@ INFO is a plist used as a communication channel."
> headline-number "-"))))
> ;; Body.
> (concat section-number
> - (org-export-data-with-translations
> + (org-export-data-with-backend
> (org-export-get-alt-title headline info)
> - ;; Ignore any footnote-reference, link,
> - ;; radio-target and target in table of contents.
> - (append
> - '((footnote-reference . ignore)
> - (link . (lambda (link desc i) desc))
> - (radio-target . (lambda (radio desc i) desc))
> - (target . ignore))
> - (org-export-backend-translate-table 'html))
> + ;; Create an anonymous back-end that will ignore
> + ;; any footnote-reference, link, radio-target and
> + ;; target in table of contents.
> + (org-export-create-backend
> + :parent 'html
> + :transcoders '((footnote-reference . ignore)
> + (link . (lambda (object c i) c))
> + (radio-target . (lambda (object c i) c))
> + (target . ignore)))
> info)
> (and tags "   ") (org-html--tags tags)))))
>
> diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
> index 1cccdc6..abf88cd 100644
> --- a/lisp/ox-odt.el
> +++ b/lisp/ox-odt.el
> @@ -1152,20 +1152,19 @@ See `org-odt--build-date-styles' for implementation
> details."
> (let* ((title (org-export-translate "Table of Contents" :utf-8 info))
> (headlines (org-export-collect-headlines
> info (and (wholenump depth) depth)))
> - (translations (nconc (mapcar
> - (lambda (type)
> - (cons type (lambda (data contents info)
> - contents)))
> - (list 'radio-target))
> - (plist-get info :translate-alist))))
> + (backend (org-export-create-backend
> + :parent (org-export-backend-name
> + (plist-get info :back-end))
> + :transcoders (mapcar
> + (lambda (type) (cons type (lambda (d c i) c)))
> + (list 'radio-target)))))
> (when headlines
> (concat
> (org-odt-begin-toc title depth)
> (mapconcat
> (lambda (headline)
> (let* ((entry (org-odt-format-headline--wrap
> - headline translations info
> - 'org-odt-format-toc-headline))
> + headline backend info 'org-odt-format-toc-headline))
> (level (org-export-get-relative-level headline info))
> (style (format "Contents_20_%d" level)))
> (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
> @@ -1731,18 +1730,22 @@ CONTENTS is nil. INFO is a plist holding contextual
> information."
> (t
> (let* ((raw (org-export-get-footnote-definition
> footnote-reference info))
> - (translations
> - (cons (cons 'paragraph
> - (lambda (p c i)
> - (org-odt--format-paragraph
> - p c "Footnote" "OrgFootnoteCenter"
> - "OrgFootnoteQuotations")))
> - (org-export-backend-translate-table 'odt)))
> - (def (let ((def (org-trim (org-export-data-with-translations
> - raw translations info))))
> - (if (eq (org-element-type raw) 'org-data) def
> - (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
> - "Footnote" def)))))
> + (def
> + (let ((def (org-trim
> + (org-export-data-with-backend
> + raw
> + (org-export-create-backend
> + :parent 'odt
> + :transcoders
> + '((paragraph . (lambda (p c i)
> + (org-odt--format-paragraph
> + p c "Footnote"
> + "OrgFootnoteCenter"
> + "OrgFootnoteQuotations")))))
> + info))))
> + (if (eq (org-element-type raw) 'org-data) def
> + (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
> + "Footnote" def)))))
> (funcall --format-footnote-definition n def))))))))
>
>
> @@ -1775,13 +1778,12 @@ CONTENTS is nil. INFO is a plist holding contextual
> information."
> "<text:span text:style-name=\"%s\">%s</text:span>"
> "OrgTag" tag)) tags " : "))))))
>
> -(defun org-odt-format-headline--wrap (headline translations info
> - &optional format-function
> - &rest extra-keys)
> - "Transcode a HEADLINE element from Org to ODT.
> -CONTENTS holds the contents of the headline. INFO is a plist
> -holding contextual information."
> - (setq translations (or translations (plist-get info :translate-alist)))
> +(defun org-odt-format-headline--wrap (headline backend info
> + &optional format-function
> + &rest extra-keys)
> + "Transcode a HEADLINE element using BACKEND.
> +INFO is a plist holding contextual information."
> + (setq backend (or backend (plist-get info :back-end)))
> (let* ((level (+ (org-export-get-relative-level headline info)))
> (headline-number (org-export-get-headline-number headline info))
> (section-number (and (org-export-numbered-headline-p headline info)
> @@ -1789,13 +1791,13 @@ holding contextual information."
> headline-number ".")))
> (todo (and (plist-get info :with-todo-keywords)
> (let ((todo (org-element-property :todo-keyword headline)))
> - (and todo (org-export-data-with-translations
> - todo translations info)))))
> + (and todo
> + (org-export-data-with-backend todo backend info)))))
> (todo-type (and todo (org-element-property :todo-type headline)))
> (priority (and (plist-get info :with-priority)
> (org-element-property :priority headline)))
> - (text (org-export-data-with-translations
> - (org-element-property :title headline) translations info))
> + (text (org-export-data-with-backend
> + (org-element-property :title headline) backend info))
> (tags (and (plist-get info :with-tags)
> (org-export-get-tags headline info)))
> (headline-label (concat "sec-" (mapconcat 'number-to-string
> @@ -1805,7 +1807,7 @@ holding contextual information."
> ((functionp org-odt-format-headline-function)
> (function*
> (lambda (todo todo-type priority text tags
> - &allow-other-keys)
> + &allow-other-keys)
> (funcall org-odt-format-headline-function
> todo todo-type priority text tags))))
> (t 'org-odt-format-headline))))
> @@ -1934,7 +1936,7 @@ holding contextual information."
> (let ((format-function
> (function*
> (lambda (todo todo-type priority text tags
> - &key contents &allow-other-keys)
> + &key contents &allow-other-keys)
> (funcall org-odt-format-inlinetask-function
> todo todo-type priority text tags contents)))))
> (org-odt-format-headline--wrap
> @@ -2149,15 +2151,14 @@ SHORT-CAPTION are strings."
> ;; will do.
> (short-caption
> (let ((short-caption (or short-caption caption))
> - (translations (nconc (mapcar
> - (lambda (type)
> - (cons type (lambda (data contents info)
> - contents)))
> - org-element-all-objects)
> - (plist-get info :translate-alist))))
> + (backend (org-export-create-backend
> + :parent (org-export-backend-name
> + (plist-get info :back-end))
> + :transcoders
> + (mapcar (lambda (type) (cons type (lambda (o c i) c)))
> + org-element-all-objects))))
> (when short-caption
> - (org-export-data-with-translations short-caption
> - translations info)))))
> + (org-export-data-with-backend short-caption backend info)))))
> (when (or label caption)
> (let* ((default-category
> (case (org-element-type element)
> --
> 1.8.3.2
>
- [O] [RFC] Changing internal representation of back-ends to defstructs, Nicolas Goaziou, 2013/07/03
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs,
Carsten Dominik <=
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs, Nicolas Goaziou, 2013/07/04
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs, Bastien, 2013/07/04
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs, Carsten Dominik, 2013/07/04
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs, Eric S Fraga, 2013/07/05
- Re: [O] [RFC] Changing internal representation of back-ends to defstructs, Bastien, 2013/07/05