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.