Fix error when exporting body only of an empty buffer

* lisp/ox.el (org-export-filter-apply-functions): Return empty string
  instead of nil when a filter returns the empty string.

* testing/lisp/test-ox.el (test-org-export/export-scope): Add test.
(test-org-export/filter-apply-functions): New test.

Reported-by: "Stefan-W. Hahn" <stefan.hahn@s-hahn.de>
<http://permalink.gmane.org/gmane.emacs.orgmode/110371>
This commit is contained in:
Nicolas Goaziou 2016-11-19 23:06:17 +01:00
parent b3125dc84b
commit 9e2dc98eef
2 changed files with 72 additions and 16 deletions

View File

@ -2472,20 +2472,24 @@ channel, as a plist. It must return a string or nil.")
(defun org-export-filter-apply-functions (filters value info)
"Call every function in FILTERS.
Functions are called with arguments VALUE, current export
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.
Functions are called with three arguments: a value, the export
back-end name and the communication channel. First function in
FILTERS is called with VALUE as its first argument. Second
function in FILTERS is called with the previous result as its
value, etc.
Functions returning nil are skipped. Any function returning the
empty string ends the process, which returns the empty string.
Call is done in a LIFO fashion, to be sure that developer
specified filters, if any, are called first."
(catch 'exit
(catch :exit
(let* ((backend (plist-get info :back-end))
(backend-name (and backend (org-export-backend-name backend))))
(dolist (filter filters value)
(let ((result (funcall filter value backend-name info)))
(cond ((not result) value)
((equal value "") (throw 'exit nil))
(cond ((not result))
((equal result "") (throw :exit ""))
(t (setq value result))))))))
(defun org-export-install-filters (info)

View File

@ -931,15 +931,30 @@ Text"
(end-of-line)
(org-export-as (org-test-default-backend)))))
;; Body only.
(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 "Text\n"
(org-test-with-temp-text "Text"
(org-export-as
(org-export-create-backend
:transcoders
'((template . (lambda (b _i) (format "BEGIN\n%sEND" b)))
(section . (lambda (_s c _i) c))
(paragraph . (lambda (_p c _i) c))))
nil nil 'body-only))))
(should
(equal "BEGIN\nText\nEND"
(org-test-with-temp-text "Text"
(org-export-as
(org-export-create-backend
:transcoders
'((template . (lambda (b _i) (format "BEGIN\n%sEND" b)))
(section . (lambda (_s c _i) c))
(paragraph . (lambda (_p c _i) c))))))))
;; Pathological case: Body only on an empty buffer is expected to
;; return an empty string, not nil.
(should
(org-test-with-temp-text ""
(org-export-as (org-test-default-backend) nil nil t))))
(ert-deftest test-org-export/output-file-name ()
"Test `org-export-output-file-name' specifications."
@ -1815,6 +1830,43 @@ Para2"
(section . (lambda (section contents info) contents))))
info)))))
;;; Filters
(ert-deftest test-org-export/filter-apply-functions ()
"Test `org-export-filter-apply-functions' specifications."
;; Functions are applied in order and return values are reduced.
(should
(equal "210"
(org-export-filter-apply-functions
(list (lambda (value &rest _) (concat "1" value))
(lambda (value &rest _) (concat "2" value)))
"0" nil)))
;; Functions returning nil are skipped.
(should
(equal "20"
(org-export-filter-apply-functions
(list #'ignore (lambda (value &rest _) (concat "2" value)))
"0" nil)))
;; If all functions are skipped, return the initial value.
(should
(equal "0"
(org-export-filter-apply-functions (list #'ignore) "0" nil)))
;; If any function returns the empty string, final value is the
;; empty string.
(should
(equal ""
(org-export-filter-apply-functions
(list (lambda (value &rest _) "")
(lambda (value &rest _) (concat "2" value)))
"0" nil)))
;; Any function returning the empty string short-circuits the
;; process.
(should
(org-export-filter-apply-functions
(list (lambda (value &rest _) "")
(lambda (value &rest _) (error "This shouldn't happen")))
"0" nil)))
;;; Footnotes