ielm – the interactive Emacs Lisp REPL

It is a wonderful thing to learn more about one’s tools.

I recently was trying to debug some Elisp code (specifically, I was writing a custom Org Mode capture function), and the behaviour was sufficiently non-obvious that I said, “I sure wish there was a REPL so I could run some test cases for my function interactively.”

Upon searching for it, I discovered that this was a built-in feature, ielm, and, to a certain bit of personal disappointment, I had probably been oblivious of this feature for 20 years or so.

Emacs is more than large enough to contain mountains of “little features” like this unnoticed.

By the way, here’s the code that took some debugging…

(defun before-gtalug (date)
  (let* ((now (decode-time)) ;;; take today
         (day (elt now 3)) ;;; extract month, year, dst, zone
         (month (elt now 4))
         (year (elt now 5))
         (dst (elt now 7))
         (zone (elt now 8))
;;; construct the 8th of the month, which is the earliest possible GTALUG date
         (eighthday (encode-time 0 0 0 8 month year zone))
;;; decode it…
         (eighth-decoded (decode-time eighthday))
;;; Grab the day of the week…
         (eighth-dow (elt eighth-decoded 6))
;;; How many days until the next tuesday???
         (days-to-tuesday
          (mod (- (+ 9 eighth-dow)) 6))
         (gtalug-tuesday (+ (elt eighth-decoded 3) days-to-tuesday)))
  (<= day gtalug-tuesday)))
(defun gtalug-month-label ()
  (let* ((now (decode-time)) ;;; take today
         (month (elt now 4))
         (year (elt now 5))
         (is-before-gtalug (before-gtalug now)))
      (if is-before-gtalug
        (format-time-string "GTALUG Q&A Topics for %B %Y"
                            (encode-time 0 0 0 1 month year))
        (if (= month 12) ;;; if december, then shift to next year
            (format-time-string "GTALUG Q&A Topics for %B %Y"
                                (encode-time 0 0 0 1 1 (+ year 1)))
(setf gtalug-month-label "")
(defun set-gtalug-month-label ()
   (setf gtalug-month-label (gtalug-month-label))
   (setq org-capture-templates
      `(("a" "Afilias" entry (file+headline "~/GitConfig/OrgDiary/Afilias.org" "Afilias")
         "* %?\nEntered on %U\n %i\n WhereWasI:%a")
        ("g" "GTALUG" entry (file+headline "~/GitConfig/OrgDiary/notes.org"
             ,(gtalug-month-label)
        )
      "* %?\nEntered on %U")
      ("n" "Note" entry (file+olp+datetree "~/GitConfig/OrgDiary/notes.org")
       "* %?\nEntered on %U\n %i\n WhereWasI:%a"))))

;;; Set a timer to re-evaluate the template about once a day
(run-at-time "1 sec" (* 3600 24) #'set-gtalug-month-label)