0

I am trying to adapt this code from https://www.emacswiki.org/emacs/DiaryMode for use in Emacs with calendar and diary.

(defun diary-schedule (m1 d1 y1 m2 d2 y2 dayname)
      "Entry applies if date is between dates on DAYNAME.  
    Order of the parameters is M1, D1, Y1, M2, D2, Y2 if
    `european-calendar-style' is nil, and D1, M1, Y1, D2, M2, Y2 if
    `european-calendar-style' is t. Entry does not apply on a history."
      (let ((date1 (calendar-absolute-from-gregorian
                    (if european-calendar-style
                        (list d1 m1 y1)
                      (list m1 d1 y1))))
            (date2 (calendar-absolute-from-gregorian
                    (if european-calendar-style
                        (list d2 m2 y2)
                      (list m2 d2 y2))))
            (d (calendar-absolute-from-gregorian date)))
        (if (and 
             (<= date1 d) 
             (<= d date2)
             (= (calendar-day-of-week date) dayname)
             (not (check-calendar-holidays date))
             )
             entry)))

The above allows recurring items having entries like &%%(diary-schedule 22 4 2003 1 8 2003 2) 18:00 History.

I prefer ISO date format, so I would like to be able to enter in ~/.emacs.d/diary entries like

%%(diary-schedule 2021 08 30 2021 12 10 1) 08:30 Recurring event

Accordingly, I have modified the aforementioned code thus:

(defun diary-schedule (y1 m1 d1 y2 m2 d2 weekday)
    ""
        (let ((date1 (calendar-absolute-from-gregorian
                 (diary-make-date y1 m1 d1)))
              (date2 (calendar-absolute-from-gregorian
                 (diary-make-date y2 m2 d2)))
              (d (calendar-absolute-from-gregorian date)))
        (if (and 
            (<= date1 d) 
            (<= d date2)
            (= (calendar-day-of-week date) weekday)
        (not (check-calendar-holidays date))
        )
            entry)))

and I set calendar-date-style to 'iso. However, when in Calendar mode, and I try to view diary for a given date (by pressing "d"), if there is a diary entry using diary-schedule, I get an error

Error (diary): Bad diary sexp at line 36 in ~/.emacs.d/diary:
(diary-schedule 2021 08 31 2021 12 10 2)
Error: (void-function check-calendar-holidays)

If I comment out the one line

(not (check-calendar-holidays date))

everything works OK.

.emacs includes the lines

(require 'calendar)

(setq calendar-date-style 'iso)

before the code above.

It seems that check-calendar-holidays should return a list of holidays that match date or nil otherwise. It also seems that check-calendar-holidays gets its input from date and that date style shouldn't matter. Perhaps I'm mistaken.

I used M-: (setq calendar-debug-sexp t) RET and then tried, so here is stack trace:

Debugger entered--Lisp error: (void-function check-calendar-holidays)
  (check-calendar-holidays date)
  (not (check-calendar-holidays date))
  (and (<= date1 d) (<= d date2) (= (calendar-day-of-week date) weekday) (not (check-calendar-holidays date)))
  (if (and (<= date1 d) (<= d date2) (= (calendar-day-of-week date) weekday) (not (check-calendar-holidays date))) entry)
  (let ((date1 (calendar-absolute-from-gregorian (diary-make-date y1 m1 d1))) (date2 (calendar-absolute-from-gregorian (diary-make-date y2 m2 d2))) (d (calendar-absolute-from-gregorian date))) (if (and (<= date1 d) (<= d date2) (= (calendar-day-of-week date) weekday) (not (check-calendar-holidays date))) entry))
  diary-schedule(2021 8 31 2021 12 10 2)
  eval((diary-schedule 2021 8 31 2021 12 10 2))
  diary-sexp-entry("(diary-schedule 2021 08 31 2021 12 10 2)" "10:15 Recurring appointment" (9 7 2021))
  diary-list-sexp-entries((9 7 2021))
  diary-list-entries((9 7 2021) 1)
  diary-view-entries(1)
  funcall-interactively(diary-view-entries 1)
  call-interactively(diary-view-entries nil nil)
  command-execute(diary-view-entries)

Symbol's function definition is void: check-calendar-holidays appears in the minibuffer.

New to Emacs and not sure how to debug. Why do I get this error?

4
  • 2
    Because the function is called calendar-check-holidays. Apparently the wiki page is very old, and the name was different, but at some point all calendar functions were renamed with the calendar- prefix.
    – NickD
    Jul 14 at 2:31
  • 1
    I fixed the name on the wiki page.
    – NickD
    Jul 14 at 2:37
  • I did some spelunking with git on the emacs sources: the renaming happened and compatibility aliases were added in 2007. The aliases were removed in 2014. You found this on the wiki in 2021. I predict that the next time that this problem will pop up will be in 2028.
    – NickD
    Jul 14 at 2:45
  • calendar-check-holidays works like a charm. Jul 14 at 11:19
0

Pursuant to @NickD's most helpful comments, the issue was indeed that check-calendar-holidays is no more and calendar-check-holidays is now the correct function, hence:

(defun diary-schedule (y1 m1 d1 y2 m2 d2 weekday &optional mark)
"Assumes calendar-date-style = iso.
Entry applies if date is between date1 and date2 
and on the specified weekday, e.g., monday = 1.
Note: Expected order of parameters passed to 
diary-make-date depends on calendar-date-style."
(with-no-warnings (defvar date) (defvar entry))
(let ((date1 (calendar-absolute-from-gregorian
         (diary-make-date y1 m1 d1)))
      (date2 (calendar-absolute-from-gregorian
         (diary-make-date y2 m2 d2)))
      (d (calendar-absolute-from-gregorian date)))
(and 
    (<= date1 d) 
    (<= d date2)
    (= (calendar-day-of-week date) weekday)
    (not (calendar-check-holidays date))
    (cons mark entry))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.