16

I wrote a function, and I want to call it via M-x, and bind it to a key. This is my function:

(defun my-function ()
    (message "This is a great function"))

If I try to call it with M-x my-function, I get the error: [no match] in the mini-buffer.

If I try to bind it to a key (or mouse click):

(global-set-key (kbd "C-c a") 'my-function)

It appears to work, but when I try to call it with C-c a, I get the error

Wrong type argument: commandp, my-function

Why can't I use my function?

Tyler
  • 21,719
  • 1
  • 52
  • 92
  • 5
    I volunteer this question as a generic response to frequently asked questions on this subject. Feel free to expand or clarify however makes sense to make the question and answer discoverable by & useful to people with similar problems! – Tyler Oct 16 '18 at 13:54
  • 1
    Thanks for doing this, Tyler. I flagged the Q for a moderator to please convert this to a community question. – Drew Oct 16 '18 at 14:46
  • One thing I wonder about is whether the title should just quote the error message. That might be easier for people to find, and it might allow for answers that do not have to do with just adding `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. – Drew Oct 16 '18 at 14:48
  • It would be good if folks now searched the wiki for, say, `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](https://emacs.stackexchange.com/q/37533/105) the question is unrelated and should be left as is (not closed). – Drew Oct 16 '18 at 14:51
  • 1
    @Drew I wasn't sure how best to 'advertise' this in the title. The commandp error only pops up with keybindings, so people running into this from the M-x direction won't see the connection. Not sure what the best balance is between a clear, concise title and a title that will pop up for all the relevant search queries. Feel free to tweak as you like! – Tyler Oct 16 '18 at 15:04
  • I think you have a good title. But it's not true that that error is raised only for attempted keybindings. Put `commandp` into the search box and you'll find several Q&A that are about this error msg but whose answers do not involve lacking `interactive`. – Drew Oct 16 '18 at 16:11
  • This looks much more discoverable, although it might help if it had the word "command" in the title. (Before posting my original question, I kept searching for things like "custom command" and finding highly specific, irrelevant answers like [this](https://emacs.stackexchange.com/questions/3048/helm-and-custom-commands) and [this](https://emacs.stackexchange.com/questions/12738/magit-custom-commands).) – David Moles Oct 16 '18 at 20:50

1 Answers1

27

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 λ
Tyler
  • 21,719
  • 1
  • 52
  • 92
  • one suggestion I'd like to add, make it clear that you need to do [C-x C-e](https://www.gnu.org/software/emacs/manual/html_node/eintr/How-to-Evaluate.html#How-to-Evaluate) before doing `M-x my-function` in your example. Also as an emacs beginner I'm really not 100% clear yet on what exactly `C-x C-e` does or when you need to run it, but it appears that uh... when you run it, it parses the buffer and overwrites `my-function` in memory because if I don't run `C-x C-e` `M-x` runs the function from the last time I ran `C-x C-e` – jrh Oct 21 '18 at 18:31
  • It would appear that `C-x C-e` [evaluates the buffer](https://www.gnu.org/software/emacs/manual/html_node/eintr/How-to-Evaluate.html#How-to-Evaluate), it seems that the result of evaluating a buffer containing a `defun` is registering the function, though [this article](https://www.gnu.org/software/emacs/manual/html_node/eintr/Lisp-Interpreter.html#Lisp-Interpreter) seems to make me think that it should just run the function, and yet the only thing shown in the minibuffer is `my-function` (implying it returns the function?), not `This is a great function`. I must be missing something here. – jrh Oct 21 '18 at 18:44
  • 1
    Thanks for your comments, @jrh. This question & answer are addressing a particular aspect of elisp, how to make a function interactive (i.e., turn function into a command). You're asking about more fundamental aspects of elisp, and are beyond the scope of this question. I recommend working through the the Emacs Lisp Intro. You seem to be confused about the difference between evaluating a function definition, which (re-)defines a function but doesn't actually call it, and calling the function, which runs the function code. – Tyler Oct 22 '18 at 15:12