A long time ago I wrote about the datefudge tool, which can be very useful to test time-related code (not only in Elisp). Today I’m going to write about another way of solving a similar problem.
I am currently building (yet another) tool on top of Org mode. This tool heavily uses the notion of “today”. I made a conscious effort to always use the org-today function to get today’s date, precisely because I want to be able to mock it for tests.
However, writing automated tests is one thing, and testing stuff manually while developing it is another – both have their place. I thought that it would be pretty cool if I could interactively make org-today return any given date, so that I’d be able to test things quickly.
One thing that bothers me is this. Assuming I write an interactive wrapper around (advice-add 'org-today :override ...), how do I make sure I won’t forget to remove that advice?
And then, an idea occurred to me. I could (again!) write my own version of execute-extended-command which would first ask for a date (using org-read-date, of course) and then run the given command with org-today advised.
;;; -*- lexical-binding: t -*-
(defun org-fake-today--create-advice (fake-date)
"Return the function used to advise `org-today'."
(lambda () fake-date))
(defun org-fake-today-execute-command (prefix-arg)
"Execute a command with `org-today' temporarily advised.
First ask the user for the date."
(interactive "P")
(advice-add
'org-today
:override (org-fake-today--create-advice
(time-to-days
(org-read-date nil t)))
'((name . org-fake-today)))
(execute-extended-command prefix-arg)
(advice-remove 'org-today 'org-fake-today))
(global-set-key (kbd "C-s-X") #'org-fake-today-execute-command)
Note the comment setting lexical-binding to t in the first line – we need the value returned from org-fake-today--create-advice to be a closure which will take the place of org-today. This means that the above snippet needs to be in a file on its own – or a part of a file where lexical binding is on.
And now I can say, for example, this: C-s-X -7 RET org-agenda RET a and see the agenda as it had been shown a week ago. How cool is that?
CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode