Elisp for adding log entries
The logs section of this site uses some simple markdown for entries. An example looks like this:
---
title: 2019
layout: log
---
## 2019-04-15
* This is a log entry.
I wanted to try writing a little bit of elisp code to streamline the process of adding new entries. It’s not exactly time-consuming to add a few new lines by hand, but reducing friction means I’m more likely to keep things updated.
Each log file is stored in _logs
inside the jekyll source directory:
- src
- _posts
- _notes
- _logs
- 2019.md
In the end I came up with the following code:
(defvar sodaware/sdf-logs-path "/path/to/jekyll/src/_logs/")
(defun sodaware/sdf-log ()
"Add a new entry to the current sodaware.sdf.org log."
(interactive)
(let* ((current-year (format-time-string "%Y"))
(current-date (format-time-string "%Y-%m-%d"))
(log-file (format "%s%s.md" sodaware/sdf-logs-path current-year)))
;; Find the log file.
(find-file log-file)
;; Add Jekyll markup if file is empty.
(when (= 0 (buffer-size))
(insert "---" "\n")
(insert "title: " current-year "\n")
(insert "layout: log\n")
(insert "---" "\n\n")
(insert (format "## %s\n\n" current-date)))
;; Attempt to find the current heading. If not found, insert it.
(sodaware/find-or-insert-heading (format "## %s" current-date) "## ")
;; Insert after.
(forward-line 2)
(insert "* \n")
(forward-line -1)
(move-end-of-line 1)))
(defun sodaware/find-or-insert-heading (heading start-of-heading)
"Find or insert HEADING before START-OF-HEADING in the current buffer."
;; Go to the start of the file.
(goto-char (point-min))
;; Search for the heading. If not found, find the start of the first heading
;; and insert before that.
(unless (search-forward heading nil t)
(goto-char (point-min))
(search-forward start-of-heading)
(move-beginning-of-line 1)
(insert "\n\n")
(forward-line -2)
(insert heading "\n")
(forward-line -1))
(move-beginning-of-line 1))
Notes
-
sodaware/sdf-logs-path
- The full path of the log directory.
-
sodaware/find-or-insert-heading
- A utility function function that searches for a headline in the current buffer. If the headline is not found, it will be inserted above the first headline in the file. It’s not Markdown specific, so something like
(sodaware/find-or-insert-heading "** heading" "** ")
would work for org-mode headlines.
-
sodaware/sdf-log
- The main function to call when adding a new entry. It opens the log file for the current year and inserts a timestamp heading before the first headline. If the file does not exist, it is created and filled with Jekyll markup and the first headline.
Future improvements
I’m not 100% happy with how things currently work. I’d like to split things up further so I can reuse the main note creation function for other projects. I often keep project development logs in markdown format and it would be handy to use the same skeleton code for adding entries to them.