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.
This is the Elisp: dialect of Lisp used in GNU Emacs (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.
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.