Before I switched to Emacs 🔍, I had a Rake 🔍 task that I invoked to create new blog posts. I’d hop on the terminal, run the task. That task would both stub out a new blog post and open the task in my editor of choice.
This worked, but the script wasn’t integrated into my text editor. So there was a slight context shift to go from I have an idea for a blog post to I’m starting that blog post.
I decided to rewrite it as a Emacs function. This interactive function, named
tor-post-new, prompts for the posts title. I fill out the title, and the function create the file with the appropriate Hugo 🔍 front matter and opens that file in a buffer.
Later in this post, I share the functions I’ve created.
By moving the function into my text editor, I reduced the friction of creating a new blog post.
, I wrote the first in the Amplifying the Blogosphere. Which got me thinking, I really should create an interactive function to ease writing entries to the Amplifying the Blogosphere series.
So I wrote
tor-post-amplifying-the-blogosphere. This function doesn’t prompt for a title, but instead derives the title based on the day. So I extracted a common function so I could have the two interactive functions use the same basic function for creating the file, filling in the front matter, and editing the new file.
And as I was thinking about it, I realized “You know, if I have an active Emacs region, I may as well grab that regions text and copy that into the new buffer.”
Elisp Functions to Ease Creating Posts
The Elisp 🔍 functions
The following code is available on Github.
(defun tor-post-new (title &optional) "Create and visit a new draft blog post for the prompted TITLE. The file for the blog post conforms to the path schema of posts for TakeOnRules.com." (interactive "sTitle: ") (tor-post---create-or-append title))
(defun tor-post-amplifying-the-blogosphere (subheading &optional) "Create and visit draft blog post for amplifying the blogosphere. The file for the blog post conforms to the path schema of posts for TakeOnRules.com." (interactive (list (if (use-region-p) (read-string "Sub-Heading: ") nil))) (tor-post---create-or-append (format-time-string "Amplifying the Blogosphere (v%Y-%m-%d)") :toc "true" :subheading subheading :series "amplifying-the-blogosphere" :tags (list "response to other blogs")))
tor-post--create function is called by both of the above functions. It’s purpose is to encode the logic and procedures for creating a new post based on the given parameters.
(defun tor-post---create-or-append (title &rest ARGS) "Create or append a post with TITLE, any ARGS are optional. ARGS: `:tags' a list of tags to add to the frontmatter. `:series' the series to set in the frontmatter. `:toc' whether to include a table of contents in the post. `:subheading' if you have an active region, use this header If there's an active region, select that text and place it." (let* ((default-directory (concat tor--repository-path "/content/posts/" (format-time-string "%Y/"))) (slug (s-dashed-words title)) (series (plist-get ARGS :series)) (tags (plist-get ARGS :tags)) (toc (plist-get ARGS :toc)) (subheading (plist-get ARGS :subheading)) (fpath (expand-file-name (concat default-directory slug ".md")))) ;; If the file does not exist, create the file with the proper frontmatter. (if (not (file-exists-p fpath)) (write-region (concat "---" "\ndate: " (format-time-string "%Y-%m-%d %H:%M:%S %z") "\ndraft: true" "\nlayout: post" "\nlicenses:\n- all-rights-reserved" "\nslug: " (format "%s" slug) "\ntitle: '" title "'" "\ntype: post" (if series (concat "\nseries: " series)) (if toc (concat "\ntoc: true")) (if tags (concat "\ntags:" (mapconcat (lambda (tag) (concat "\n- " tag)) tags ""))) "\n---\n") nil fpath)) ;; If we have an active region, append that region's content to ;; the given file. (if (use-region-p) (write-region (concat (if subheading (concat "\n## " subheading "\n\n")) (buffer-substring (region-beginning) (region-end))) nil fpath t)) ;; Finally open that file for editing. (find-file fpath))) ""))) "\n---\n") nil fpath nil nil t)) ;; If we have an active region, append that region's content to ;; the given file. (if (use-region-p) (write-region (concat "\n## YOUR H2 HERE\n\n" (buffer-substring (region-beginning) (region-end))) nil fpath t nil nil nil)) ;; Finally open that file for editing. (find-file fpath)))
With the new
tor-post-amplifying-the-blogosphere function, and the “grab the active region’s text”, I’m aware of further workflow refinements. I’m also seeing that I’m drawing closer to a possible event horizon in which I shift fully to Org-mode 🔍 for blogging.
I can almost feel the tug of Org-mode.
Let’s dive into that just a bit.
The goal of the
tor-post-amplifying-the-blogosphere function is to make it easy to highlight things I’ve found during the day. And in it’s current implementation, the first thing I find is easier to acknowledge.
For those familiar with Org-mode, I have implemented a naive and rudimentary capture process. I am aware that Org-mode’s current tooling would make easier the
Amplifying the Blogosphere process.
However, I’ve only written one post in the Amplifying the Blogosphere, so I’m not about to begin migrating my blog from Hugo to Org-mode. However, knowing that there’s tooling that supports the behavior I want to develop raises the possibility of a migration.
Another way to look at this is to think about the functional desires that I might have. When I’m reading articles, I want an easy way to capture the title, URL, and perhaps a block quote of that article. With that captured information, I want to either create a new for today Amplifying the Blogosphere post or append to an existing one.
Of course, I can mimic quite a bit of this by adding to a copy buffer or Emacs kill ring.
So for now, I’ll proceed with what I have and be mindful of possible future work.
An earlier version of myself might have jumped at implementing these speculative changes. But, now in my third decade of professional software development, I see this premature feature development as a questing beast.
In a way, this builds on my observations from Bringing the Whole Toolkit to Problem-Solving; Yes, I might learn something new in pursuing it, but is it actually worth spending that time?
I don’t know, but I do know that slowing down my personal implementation tendencies has always yielded a better solution and conserved my energy to address the important issues. And realistically, I don’t even know if I have a problem that warrants a solution.