1

I'm trying to load the defhook package without success. The code defines a macro using defmacro* (with the asterisk at the end), and I can't find any info about it. (The fact that the '*' is ignored by search engines doesn't help either.)

The code in question is as follows:

(defmacro* defhook (name (hook-sym &key 
               (op 'add)
                               (interactive-spec t)
               (append nil)
               (validate-hook-name t)
                               (eval-after nil)
                               (local nil)
                               (hook-args nil))
                     &rest body)
 ...

And when I start Emacs with --debug-init, I get the following error:

Debugger entered--Lisp error: (void-function defmacro*)
  (defmacro* defhook (name (hook-sym &key (op 'add) (interactive-spec t) (append nil) (validate-hook-name t) (eval-after nil) (local nil) (hook-args nil)) &rest body) "Create a hook function and add it to the appropria..." nil (progn (or (not (null defhook-user-prefix)) (cl--assertion-failed '(not (null defhook-user-prefix)) nil (list (null defhook-user-prefix)) (list))) nil) (let* ((post-hook-action t) (post-defhook-action t) (our-name (symbolp name)) (our-local local) (our-append append) (our-op (cl-assert-rtn op (member op '(add delete no-op)) t)) (our-hook-sym (defhook-check-sym-syntax hook-sym "HOOK-NAME")) (our-hook-args hook-args) (tmp-int-spec interactive-spec) (our-int-spec (if (eq tmp-int-spec t) (interactive) tmp-int-spec)) (our-val-hook-name validate-hook-name) (our-eval-after (or eval-after 'simple)) (our-hook-name (cl-assert-rtn our-hook-sym (or (not our-val-hook-name) (string-match-p "-\\(hook\\|function\\|hooks\\|functions\\)$" (symbol-name our-hook-sym))) t)) (our-func-name (defhook-create-function-name (defhook-check-sym-syntax name "NAME") our-hook-sym)) (our-func-sym (intern our-func-name)) (began-in-hook (member our-func-sym (if (boundp our-hook-sym) (symbol-value our-hook-sym) (set our-hook-sym nil)))) (our-body body) (our-docstring (if (stringp (car our-body)) (progn (setq our-docstring (car-safe ...))))) (defhook-done-form (list 'defhook-done (list 'quote our-func-sym) (list 'quote our-hook-sym) (list 'quote our-op) (list 'quote began-in-hook) ''nil (list 'quote our-hook-args)))) (if :Comment-Ignore-Test-Code nil (defhook test1 (foo-hook) (message "foo-hook-test1") (message "foo-hook-test1 again")) (defhook test2 (foo-hook) (message "foo-hook-test 2"))) (cond ((eq 'no-op our-op) defhook-done-form) ((eq 'delete our-op) (remove-hook our-hook-sym our-func-sym) defhook-done-form) (t (remove-hook our-hook-sym our-func-sym) (let ((defhook-delayed-done-form (list ... ... ... ...)) (defhook-executed-form (list ... ... ...))) (list 'let (list (list ... ...)) (list 'eval-after-load (list ... our-eval-after) (list ... ...)) (list 'defhook-done (list ... our-func-sym) (list ... our-hook-sym) (list ... our-op) (list ... began-in-hook) 'pending-load (list ... our-hook-args))))))))
  eval-buffer(#<buffer  *load*-955329> nil "~/.emacs.d/org-status/defhook.el" nil t)  ; Reading at buffer position 30747
  load-with-code-conversion("~/.emacs.d/org-status/defhook.el" "~/.emacs.d/org-status/defhook.el" nil nil)
  load("~/.emacs.d/org-status/defhook.el")
  eval-buffer(#<buffer  *load*> nil "~/.emacs.d/init.el" nil t)  ; Reading at buffer position 1253
  load-with-code-conversion("~/.emacs.d/init.el" "~/.emacs.d/init.el" t t)
  load("~/.emacs.d/init" noerror nomessage)
  startup--load-user-init-file(#f(compiled-function () #<bytecode 0x1ff01aa07dd1>) #f(compiled-function () #<bytecode 0x1ff01aa07de5>) t)
  command-line()
  normal-top-level()

Removing the asterisk from defmacro produces another error:

 entered--Lisp error: (invalid-function (lambda (name (hook-sym &key (op 'add) (interactive-spec t) (append nil) (validate-hook-name t) (eval-after nil) (local nil) (hook-args nil)) &rest body) "Create a hook function and add it to the appropria..." (progn (or (not (null defhook-user-prefix)) (cl--assertion-failed '(not (null defhook-user-prefix)) nil (list (null defhook-user-prefix)) (list))) nil) (let* ((post-hook-action t) (post-defhook-action t) (our-name (symbolp name)) (our-local local) (our-append append) (our-op (cl-assert-rtn op (member op '...) t)) (our-hook-sym (defhook-check-sym-syntax hook-sym "HOOK-NAME")) (our-hook-args hook-args) (tmp-int-spec interactive-spec) (our-int-spec (if (eq tmp-int-spec t) (interactive) tmp-int-spec)) (our-val-hook-name validate-hook-name) (our-eval-after (or eval-after 'simple)) (our-hook-name (cl-assert-rtn our-hook-sym (or (not our-val-hook-name) (string-match-p "-\\(hook\\|function\\|hooks\\|functions\\)$" ...)) t)) (our-func-name (defhook-create-function-name (defhook-check-sym-syntax name "NAME") our-hook-sym)) (our-func-sym (intern our-func-name)) (began-in-hook (member our-func-sym (if (boundp our-hook-sym) (symbol-value our-hook-sym) (set our-hook-sym nil)))) (our-body body) (our-docstring (if (stringp (car our-body)) (progn (setq our-docstring ...)))) (defhook-done-form (list 'defhook-done (list 'quote our-func-sym) (list 'quote our-hook-sym) (list 'quote our-op) (list 'quote began-in-hook) ''nil (list 'quote our-hook-args)))) (if :Comment-Ignore-Test-Code nil (defhook test1 (foo-hook) (message "foo-hook-test1") (message "foo-hook-test1 again")) (defhook test2 (foo-hook) (message "foo-hook-test 2"))) (cond ((eq 'no-op our-op) defhook-done-form) ((eq 'delete our-op) (remove-hook our-hook-sym our-func-sym) defhook-done-form) (t (remove-hook our-hook-sym our-func-sym) (let ((defhook-delayed-done-form ...) (defhook-executed-form ...)) (list 'let (list ...) (list ... ... ...) (list ... ... ... ... ... ... ...))))))))
  (lambda (name (hook-sym &key (op 'add) (interactive-spec t) (append nil) (validate-hook-name t) (eval-after nil) (local nil) (hook-args nil)) &rest body) "Create a hook function and add it to the appropria..." (progn (or (not (null defhook-user-prefix)) (cl--assertion-failed '(not (null defhook-user-prefix)) nil (list (null defhook-user-prefix)) (list))) nil) (let* ((post-hook-action t) (post-defhook-action t) (our-name (symbolp name)) (our-local local) (our-append append) (our-op (cl-assert-rtn op (member op '...) t)) (our-hook-sym (defhook-check-sym-syntax hook-sym "HOOK-NAME")) (our-hook-args hook-args) (tmp-int-spec interactive-spec) (our-int-spec (if (eq tmp-int-spec t) (interactive) tmp-int-spec)) (our-val-hook-name validate-hook-name) (our-eval-after (or eval-after 'simple)) (our-hook-name (cl-assert-rtn our-hook-sym (or (not our-val-hook-name) (string-match-p "-\\(hook\\|function\\|hooks\\|functions\\)$" ...)) t)) (our-func-name (defhook-create-function-name (defhook-check-sym-syntax name "NAME") our-hook-sym)) (our-func-sym (intern our-func-name)) (began-in-hook (member our-func-sym (if (boundp our-hook-sym) (symbol-value our-hook-sym) (set our-hook-sym nil)))) (our-body body) (our-docstring (if (stringp (car our-body)) (progn (setq our-docstring ...)))) (defhook-done-form (list 'defhook-done (list 'quote our-func-sym) (list 'quote our-hook-sym) (list 'quote our-op) (list 'quote began-in-hook) ''nil (list 'quote our-hook-args)))) (if :Comment-Ignore-Test-Code nil (defhook test1 (foo-hook) (message "foo-hook-test1") (message "foo-hook-test1 again")) (defhook test2 (foo-hook) (message "foo-hook-test 2"))) (cond ((eq 'no-op our-op) defhook-done-form) ((eq 'delete our-op) (remove-hook our-hook-sym our-func-sym) defhook-done-form) (t (remove-hook our-hook-sym our-func-sym) (let ((defhook-delayed-done-form ...) (defhook-executed-form ...)) (list 'let (list ...) (list ... ... ...) (list ... ... ... ... ... ... ...)))))))(defhook-emacs-startup-hook-monitor (emacs-startup-hook) "Used by `defhook-startup' to determine if `emacs-s..." (setq defhook-emacs-startup-hook-monitor t))
  (defhook defhook-emacs-startup-hook-monitor (emacs-startup-hook) "Used by `defhook-startup' to determine if `emacs-s..." (setq defhook-emacs-startup-hook-monitor t))
  eval-buffer(#<buffer  *load*-549255> nil "~/.emacs.d/org-status/defhook.el" nil t)  ; Reading at buffer position 31058
  load-with-code-conversion("~/.emacs.d/org-status/defhook.el" "~/.emacs.d/org-status/defhook.el" nil nil)
  load("~/.emacs.d/org-status/defhook.el")
  eval-buffer(#<buffer  *load*> nil "~/.emacs.d/init.el" nil t)  ; Reading at buffer position 1253
  load-with-code-conversion("~/.emacs.d/init.el" "~/.emacs.d/init.el" t t)
  load("~/.emacs.d/init" noerror nomessage)
  startup--load-user-init-file(#f(compiled-function () #<bytecode 0x1fe411c5883d>) #f(compiled-function () #<bytecode 0x1fe411c58851>) t)
  command-line()
  normal-top-level()

Do you have any pointers to fix this?

1
  • Change defmacro* to cl-defmacro, and add (require 'cl-lib) to the file that uses it. – Drew Jan 17 at 0:47
1

Add this line to your init file or to the beginning of the old package:

(require 'cl)

Emacs Lisp is a dialect of the Lisp language family. Common Lisp is another dialect of Lisp with more features and an official standard. Emacs has a Common Lisp emulation package which provides features found in Common Lisp but not in Emacs Lisp.

The modern way to use Common Lisp emulation is (require cl-lib). The cl-lib package is distributed with Emacs. To avoid name conflicts, the functions and macros in this package have a name that starts with cl-. For example, there's a cl-defmacro which extends Emacs Lisp's built-in defmacro with extra features from Common Lisp, and there's a cl-reduce which implements Common Lisp's reduce function.

The old way is (require 'cl). The modern package called cl (also distributed with Emacs) uses cl-lib to emulate an old cl package with different naming conventions: functions and macros that don't exist in Emacs Lisp just have their name from Common Lisp (e.g. reduce), and for those that exist in Emacs Lisp, the cl package calls its version with an asterisk at the end, e.g. defmacro*.

So defmacro* is the old-style Common Lisp emulation version of defmacro, provided by cl.

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.