Суть в том, что есть разница между функцией и командой .
В Emacs lisp функции по умолчанию не могут вызываться в интерактивном режиме. Это означает, что вы не можете получить к ним доступ M-x
или привязать их к клавише или щелчку мыши. Если вы хотите сделать это, вам нужно явно объявить функцию interactive
, что вы делаете, добавляя (interactive)
форму в качестве первой строки в теле (после строки документации). Интерактивная функция называется командой. Это объяснено в руководстве: (info "(elisp) Using Interactive")
(онлайн-версия) .
Вы видите сообщение об ошибке Wrong type argument: commandp, my-function
, указывающее, что вы пытаетесь вызвать функцию в интерактивном режиме, но эта функция не является командой .
Чтобы объяснить фактическую ошибку, буква p
часто используется в lisp для обозначения предиката или теста. В этом случае Emacs проверяет, является my-function
ли это команда, использующая тест commandp
. Это не так, что приводит к ошибке. Подобные ошибки появляются, когда вы используете объект неправильного типа: если Emacs ожидает строку и вы передаете символ, вы можете увидеть ссылку stringp
, например.
Чтобы ответить на заданный вопрос, необходимо добавить (interactive)
строку в определение:
(defun my-function ()
(interactive)
(message "This is a great function"))
Существует множество вариантов interactive
формы, поддерживающих все виды передачи информации в вашу функцию. Проверьте руководство для всех деталей.
Клавиатурные макросы являются особым случаем в этом контексте. Макрос клавиатуры - это последовательность событий ввода, представленная в виде строки. Макросы клавиатуры ведут себя как команды, поэтому вы можете связать их с клавишами, не беспокоясь о добавлении interactive
объявления. Например, в следующем:
(global-set-key (kbd "C-c l") "λ")
"λ"
это макрос клавиатуры, поэтому мы можем связать его C-c l
без проблем. Если мы пытаемся сделать то же самое с функцией, мы должны быть уверены, что определим функцию как 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 λ