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.