Creating a new post (redux)

Now that we’ve got a way to ask the user to choose a blog, as well as ways to extract a post structure from a buffer and merge a post structure back into a buffer, we can actually write our function for creating a new post.

It turns out it’s pretty simple:

(defun org-blog-new ()
  "Create a new buffer primed for a blog entry.

Get a name for the blog from the user, and create a new buffer
with the name of the blog, a timestamp reflecting the current
time, and a number of other empty fields that the user may wish
to fill in."
  (interactive)
  (let ((name (org-blog-get-name)))
    (switch-to-buffer (generate-new-buffer (format "*org-blog/%s*" name)))
    (org-mode)
    (org-blog-mode)
    (org-blog-buffer-merge-post `((:blog . ,name)
                                  (:category . "")
                                  (:date ,(current-time))
                                  (:excerpt . "")
                                  (:format . "post")
                                  (:status . "publish")
                                  (:tags . "")
                                  (:title . "")
                                  (:type . "post")))))

The docstring lays it all out, really—get a blog name, set up a buffer, turn on org-mode and org-blog-mode and merge in a basically-empty post structure.

Now some might wonder why I don’t just slap a default chunk of string content into the buffer, rather than merging a post structure that’s got a bunch of empty fields into the buffer, as it would probably be less cumbersome that way.

The answer is that down the road I would like for people to be able to set some of the fields in the default post structure in the definition of the blog, so we have a standard way to set initial defaults on a per-blog basis.

This might seem like overkill, but I’m thinking of this scenario: say you have a blog that’s aggregated on Planet Foo. However, in addition to your interest in Foo, you are also a follower of US politics—and when you post about that, there’s always people getting riled up. Most people in that situation will ask to have the planet pull a feed from a particular category or tag, so that only posts about Foo go to the planet. If you’re like me, though, you may forget to tag all Foo posts appropriately, and so some content would get missed. With this mechanism in place, it would be possible for you to have a “foo” blog definition that included (:category . "Foo") so that when you did org-blog-new, you could choose the “foo” blog and get a preloaded template that will make sure your post goes to the right place.

The code to do that obviously isn’t there yet—hence our hard-coded post structure—but I don’t think it will be too hard to implement down the road, and I think it could be a compelling feature.

Now, with all that out of the way, let’s look at one of the tests:

  (ert-deftest ob-test-org-blog-new-from-alist ()
    "Test creating a new blog post with an alist"
    (with-mock
     (stub current-time => '(20738 4432))
     (let ((org-blog-alist '(("bar")))
           (post-string "\
#+POST_BLOG: bar
#+POST_CATEGORY: 
#+DATE: [2013-01-25 Fri 00:00]
#+DESCRIPTION: 
#+POST_STATUS: publish
#+KEYWORDS: 
#+TITLE: 
#+POST_TYPE: post
"))
       (org-blog-new)
       (should (string= (org-no-properties (buffer-string)) post-string)))))

As a practical matter, it is simplest to stub out current-time so that we can have a predictable time string (in the actual source there are also variations that test with stubs for completing-read, just like in our org-blog-get-name tests). We call org-blog-new, and examine the resulting content for sanity. Pretty simple.

So, that’s it for setting up for a new post. The next installment will start to tackle the question of posting to a blog.