コアポイントは、関数とコマンドに違いがあるということです。
Emacs lispでは、関数はデフォルトでは対話的に呼び出すことができません。つまりM-x
、キーやマウスのクリックを介してアクセスしたり、バインドしたりすることはできません。それをしたい場合は、関数を明示的に宣言する必要がありますinteractive
。これ(interactive)
は、本文の最初の行として(ドキュメント文字列の後に)フォームを追加することによって行います。インタラクティブ機能はコマンドと呼ばれます。これはマニュアルで説明されています:((info "(elisp) Using Interactive")
オンライン版)。
表示されるエラーメッセージWrong type argument: commandp, my-function
は、関数をインタラクティブに呼び出そうとしているが、その関数はコマンドではないことを示しています。
実際のエラーを説明するために、この文字p
はしばしば述語またはテストを示すためにLispで使用されます。この場合、Emacsはmy-function
testを使用したコマンドかどうかをテストしてい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 λ