The core point is that there is a difference between a function and a command.
In Emacs lisp, functions are not interactively callable by default. That means you can't access them via M-x
or bind them to a key or mouse click. If you want to do that, you need to explicitly declare the function to be interactive
, which you do by adding an (interactive)
form as the first line in the body (following the documentation string). An interactive function is called a command This is explained in the manual: (info "(elisp) Using Interactive")
(online version).
The error message you see, Wrong type argument: commandp, my-function
, is indicating that you're trying to call a function interactively, but that function isn't a command.
To explain the actual error, the letter p
is often used in lisp to indicate a predicate or test. In this case, Emacs is testing my-function
to see if it is a command using the test commandp
. It isn't, which leads to the error. Similar errors pop up whenever you use an object of the wrong type: if Emacs expects a string and you pass a symbol, you might see a reference to stringp
, for example.
To answer the question as asked, you need to add the (interactive)
line to the definition:
(defun my-function ()
(interactive)
(message "This is a great function"))
There are a lot of options for the interactive
form, supporting all kinds of ways of passing information to your function. Check the manual for all the details.
Keyboard macros are a special case in this context. A keyboard macro is a sequence of input events, represented as a string. Keyboard macros behave like commands, so you can bind them to keys without worrying about adding an interactive
declaration. For example, in the following:
(global-set-key (kbd "C-c l") "λ")
"λ"
is a keyboard macro, so we can bind it to C-c l
without a problem. If we try to do the same thing with a function we have to be sure to define the function as interactive
:
(global-set-key (kbd "C-c k")
(lambda () (insert "λ"))
;; C-c k is undefined! We tried to bind it to a function
(global-set-key (kbd "C-c m")
(lambda () (interactive) (insert "λ"))
;; C-c m is bound to a command that inserts λ
interactive
- e.g., sometimes a command disappears from a new version of a library. The error can be raised in any context where Emacs expects a command.commandp
, to try to find other Qs that can be closed as duplicates of this one. Be careful to read the Q&A, though, as some are different. In some cases, the answer (and the Q context) might be worth repeating here. In other cases the question is unrelated and should be left as is (not closed).