As part of writing for my blog, I need to start with a file. I derive the filename from the post’s title. Sometimes, I find myself wanting to change the post’s title.
As a matter of preference, I want the title, the filename, and the slug of the Uniform Resource Locator (URL 📖) to align. I previously wrote an elisp function (tor-post-new
) to create a new blog post. That function follows my naming preferences.
Below is that function.
The tor-post-new
function
This is the Emacs Lisp (elisp 📖) to create a new TakeOnRules.com blog post.
(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: ")
(let* ((default-directory (concat tor--repository-path
"/content/posts/"
(format-time-string "%Y/")))
(fpath (concat default-directory (s-dashed-words title) ".md"))
(slug (s-dashed-words title)))
(write-region (concat
"---"
"\ndate: " (format-time-string "%Y-%m-%d %H:%M:%S %z")
"\ndraft: true"
"\nlayout: post"
"\nlicenses:\n- all-rights-reserved"
"\nslug: " slug
"\ntitle: '" title "'"
"\ntype: post"
"\n---\n")
nil (expand-file-name fpath) nil nil nil t)
(find-file (expand-file-name fpath))))
With the above, I type M-x tor-post-new
and fill in the blog posts title. This creates a configured file (and buffer) for me to start writing a blog post.
Earlier today, in writing Conceptualizing a Process for Where and How to Publish the Thing, I had a different working title. I decided to change the title.
To conform to my preference, I chose to replace the title, slug, and renamed the file. Nothing complicated.
I do this a few times a year, but figured I’d practice my elisp and write jnf/retitle-tor-content
, a function that retitles a blog post. Below is that function.
The jnf/retitle-tor-content
function
This is the elisp to re-title a TakeOnRules.com blog post.
(defun jnf/retitle-tor-content (&optional title)
"Replace the given buffer's title with the new TITLE.
This function will: replace the content's title, update the slug,
and rename the buffer."
(interactive "sTitle: ")
(let* ((metadataTitle (concat "title: '" title "'"))
(slug (s-dashed-words title))
(metadataSlug (concat "slug: " slug))
(filename (buffer-file-name))
(new-filename (concat (file-name-directory filename)
slug
".md")))
;; Replace the title metadata entry
(goto-char (point-min))
(while (search-forward-regexp "^title:.*$" nil t)
(replace-match metadataTitle))
;; Replace the slug metadata entry
(goto-char (point-min))
(while (search-forward-regexp "^slug:.*$" nil t)
(replace-match metadataSlug))
;; Need to save before we rename the buffer
(save-buffer)
;; Rename the buffer, accounting for version control
(cond
((vc-backend filename)
(vc-rename-file filename new-filename))
(t
(rename-file filename new-filename t)
(set-visited-file-name new-filename t t)))
;; Report filename change
(message "Renamed %s -> %s" filename new-filename)))
All told, this took about 45 minutes; I’ll never save that much time from this function. However, I continued to learn more about Emacs (Emacs 📖). I took actions reinforcing that I can extend my text editor to conform to my uses. And I have something to contribute to the larger group of Emacs adopters.