Refactoring

So I moved on to adding The Watcher blog which is an accomplishment in moving from a single to multiple blog setup as well as challenge in refactoring my scripts into a library and besides I need to refactor. So the library is in org-jekyll-blogger.el and here I talk about my sensibilities.

Initial Goals

Since this a working version, here are my goals:

  • Create a draft
  • Post a draft
  • Find a post

At its core, that all I really want to do. Write and die. To explain further this is the workflow: create a draft, do something else, find the draft, thing again, maybe post it, sleep, sleep, review post for errors, publish. That's kinda my workflow more or less.

So here I will talk about my experience in working with it

Previous Structure

When I write a blog entry, I have to deal with to git repositories: my private org posts and my public jekyll site. I have to emphasize private and public, I would just have one structure to hold all but one would see things that aren't ready for public consumption. The good and sad thing about having a GitHub page. Copying repo commit message is quite a contrivance.

So in my script I define a project and publish root both pointing to said repositories. Through the magic of org-publish and org-publish-project-alist, it is pretty trivial to convert the org posts to jekyll compliant html files. So I guess there's nothing to talk about there.

The challenge is converting this structure to support multiple blogs which means multiple roots of sorts. So the design should support multiple roots and update the use of publishing.

Design

My design to create three objects:

Project
This represents the root of the org post and the publishing to the jekyll directory.
Blog
This represents a project blog structure.
Post
This represents a post(or draft) in a blog.

Simple design really but took me a while to draft. I will elaborate on the use of each one from a holistic sense.

Project

A project is an object that holds primarily the project and publish root. Aside from creating the folder for existence, it creates a master or project publish command which triggers each related blog's own publish command. So whenever a new blog is linked to a project, it syncs the master publish command to include that blogs publish command.

Blog

A blog is an object that holds the meat of the blog structure. Also it creates the blog structure that contains drafts, posts and images and possibly more. More importantly it creates a blog publish command which contains a content and asset publish command, it is faster to use the content publish command than publish the whole project; thankfully, there is org-publish-current-file which figures out which command to use which finds the content publish.

Post

The actual content object which is the post or draft itself. In this structure, one has to find the project, the blog directory, the post or draft directory and then make the file there and also is a nuance for a draft to just contain the title but a post must contain a date prefix format so the command must do all those.

Details

Before I continue with the simple design, there are details that I mulled over in creating this.

Interface

So given all those ideas, the commands org-jekyll-blogger-create-draft asks you to select a defined project, then blogs from those project, then the name of the draft. So I've been mulling over that single interface after experiencing magit, prodigy and helm; is this multiple choice interface the best representation?

The problem with my interface is that I only have one project and two blogs but I still have to select them, a default or previously selected scheme might work but I feel it might make the flow inconsistent where you are working in one blog but want to work in the other but got hampered by that scheme which I means a trade-off between consistency and convenience. For now I am okay with a consistent interface.

The other command that challenges this interface is org-jekyll-blogger-find-draft which asks you to select a project and blog then select a post or draft. The problem lies in the representation and sorting, should you also sort draft and post date and how will you display it. Since I am using helm I am more inclined to display with a face and formatting, but what about ivy? Or is better to display all project and blogs post and filter there?

So many questions but I guess the natural route would satisfy completing-read. Having a custom buffer like magit or prodigy is a thing to consider in making an interface.

Alist vs Plist

In creating the objects, I did not want to use classes since I am a functional programmer but rather I needed structs or records. So the natural choice for me was to use an association list or alist. I like the concept of list of key-value pairs but it isn't easy to write a list of key properties. The alternative is to use a property list or plist which is a list of paired symbols and values. For me it just feels a little more symbolic and contextual.

The sad thing about plist is that it has no support for merging lists and finding keys which is bonkers. I needed this simple functionality to merge post options and headers. When working with jekyll, you have to have preamble of org options and an front matter export block header. So I decided to have default options and headers, passed to a project, passed and merged by the blog options and headers, then finally to a post which inserts into the post. So merging properties is a key thing I need.

I don't need dash for a simple library such as this but alternatives are maps and kv which depend on dash but also add more functions that I don't need. Although I use them in my configuration, I don't really need all the extra bulk. Merging properties in an alist is simply appending lists but it looks ugly once you print it out. So I wrote my own and I don't like the feel of it that there is no native support for such but who am I to talk? But that is one lesson, not adding extra dependencies when writing libraries.

Between alist and plist, I like representing objects with plist but not much in terms of functionality but support would be nice.

Namespace

Since my file name is org-jekyll-blogger, I have to name my library the same but also prefix my functions with the same name which leads to very long names such as org-jekyll-blogger-post-draft. Thankfully, smex helps me get that name quick but the length and typing is cumbersome specially when you're writing and testing it out. I would rather type it though than have an abstraction layer of typing namespacing which might just add a layer in testing it out but I guess I'm good.

Another thing is the naming convention, whether to use a / or a - to denote a namespace delimiter, then there is the double -- delimiter to represent private variables. Although defcustom, defvar is enough to understand the intention, viewing it through describe-variable does not say much. For example, shm has both / and - to represent the public and private symbols. I am not aware of a real solution for this but when writing my configuration, I use my prefix fn/ but when writing libraries I would write it as fn-.

Aside from my gripes with it, it is not hard to follow but rather jarring that modules aren't really a thing here. I wonder what the Zen of Python has to say about it.

Prototype

So with that, I crafted the simple library with three core commands:

  • org-jekyll-blogger-create-draft
  • org-jekyll-blogger-post-draft
  • org-jekyll-blogger-find-draft

I have to admit it was easy to write although I think slow. Sigh. Instead of writing about it, here's a small screencast on what it looks like…

… and my screencast tool is broken. Looks like I have a lot to explain. I guess I'll just leave it that for now but honestly I have to get all my tools working.

Extra Features

Simple really but I do note there are other features including the leftovers from my original script such as:

  • Auto publish a post on save
  • Push to GitHub
  • Sync project blog structure to the published structure
  • Prodigy integration
  • Categories and tag completion

I can shiv the first one quite quickly, what's a post without a snippet?

(add-hook 'after-save-hook
          (lambda ()
            (save-excursion
              (org-publish-current-file))))

I find it easy to add more features if I wanted. I foresee the use of hooks and to add the git integration, structure sync and what not. I am aware of an org-jekyll library but it is no longer used by the author so it might not be doing the job he wants. Better to write your own right? Right? If you're bored like me then yes.

Working Flow

Things are pretty much incremental and more to add on the wish list. At least I am happy that I can write two blogs that challenge my creativity more although I rarely write on one. Although my creativity has been dipping, I will write or die trying.