Jaunder

Post by mdorman

M
Michael Alan Dorman@mdorman

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.