Moving to the 8.0 exporter
Moving to the new exporter
One of the TODO items I wanted to finish before making an org-blog 1.0
release was to convert to the new exporter present in org-mode 8.0.
A couple of weeks ago, I looked at turning a buffer into a post
structure. I commented at the time that I wasn't 100% certain why the
code even worked. I also commented in a later post that there was some
unfortunate redundancy in the way certain things were being done. I'm
pleased to say that both issues are addressed.
First off, I created a blog back-end for the new exporter:
(org-export-define-derived-backend 'blog 'html
:options-alist org-blog-buffer-options-alist)
The org-blog-buffer-options-alist that it references is a structure
that's created on the fly:
(defconst org-blog-buffer-options-alist
(reduce
(lambda (l i)
(let ((field (plist-get (cdr i) :attr)))
(if (string-prefix-p "POST_" field t)
(cons (list (car i) field nil nil t) l)
l)))
org-blog-post-mapping
:initial-value nil))
That's basically plucking all of the items out of the
org-blog-post-mapping field whose text names start with "POST_".
(defconst org-blog-post-mapping
'((:blog :attr "POST_BLOG" :from-buffer org-blog-property-strip)
(:category :attr "POST_CATEGORY" :from-buffer org-blog-property-split)
(:date :attr "DATE" :from-buffer org-blog-date-format)
(:description :attr "DESCRIPTION" :from-buffer org-blog-property-strip)
(:id :attr "POST_ID" :from-buffer org-blog-property-strip)
(:keywords :attr "KEYWORDS" :from-buffer org-blog-property-split)
(:link :attr "POST_LINK" :from-buffer org-blog-property-strip)
(:name :attr "POST_NAME" :from-buffer org-blog-property-strip)
(:parent :attr "POST_PARENT" :from-buffer org-blog-property-strip)
(:status :attr "POST_STATUS" :from-buffer org-blog-property-strip)
(:title :attr "TITLE" :from-buffer (lambda (v i) (org-blog-property-strip (car v) i)))
(:type :attr "POST_TYPE" :from-buffer org-blog-property-strip)))
Then, to do the actual deed, we call org-export-as, and use a reduce
loop to do any of the translations called out in the list above.
(defun org-blog-buffer-extract-post ()
"Transform a buffer into a post.
We do as little processing as possible on individual items, to
retain the maximum flexibility for further transformation."
(let ((content
(org-export-as 'blog nil nil t '(:preserve-breaks nil
:section-numbers nil
:with-tags nil
:with-toc nil
:with-todo-keywords nil)))
(attrs
(org-export-get-environment 'blog)))
(sort
(reduce
(lambda (l i)
(let ((v (plist-get attrs (car i)))
(filter (plist-get (cdr i) :from-buffer)))
(if v
(cons (cons (car i) (if filter
(funcall filter v attrs)
v)) l)
l)))
org-blog-post-mapping
:initial-value (when content
(list (cons :content content))))
(lambda (a b)
(string< (car a) (car b))))))
Although the overall code hasn't gotten signficantly shorter, it's much clearer---it uses more centralized structures to gather together information, and it applies more general transformations defined in structures rather than conditional statements.