anything.elプログラマ向け最新情報

Emacs本を書きました

anything.elフレームワークは徐々に進化しています。 ユーザーとして使いやすくする一方、より簡単にプログラミングできるように改良しています。 なるべく非互換性を導入しないように特に気をつけています。 初期に作られた情報源も動くはずです。 動かない場合はanything.elのバグの可能性があります。

anything関数とキーワード引数

anything関数がキーワード引数を受け付けるようになりました。 これにより、可読性が上がります。 おそらく一番目立つ最新機能でしょう。

もちろん、通常の引数も使えるので、お好きな方をどうぞ。

基本キーワード

anything関数の通常の引数に対応するキーワードは以下の通りです。

:sources情報源
:input最初の入力パターン
:promptプロンプト
:resumetのとき、直前のanythingセッションを復元、noresumeのとき復元不能にする
:preselect最初に選択する候補。表示文字列そのものか正規表現で指定する。
:bufferanythingバッファ
:keymapキーマップ

以下の両者は等価です。


;; 従来の引数
(anything sources input prompt resume preselect buffer keymap)
;; キーワード引数
(anything :sources sources :input input :prompt prompt :resume resume

preselect preselect :buffer buffer :keymap keymap)
例:anything-other-bufferとの対比

情報源とanythingバッファを指定するanything-other-buffer関数は相変わらず便利です。 以下の3つは等価です。


;; anything-other-buffer
(anything-other-buffer sources buffer)
;; anything(通常の引数)
(anything sources nil nil nil nil buffer)
;; anything(キーワード引数)
(anything :sources sources :buffer buffer)

coerce属性

coerce属性を指定することで、アクションに渡す直前に型変換を施します。

導入前

type属性を指定することで、オブジェクトの型に応じてアクションなどを再利用できます。 しかし、アクションには文字列化された状態で渡るため、各々のアクション関数で元のオブジェクトへ復元する必要があります。 そのため、余計な関数(あるいはラムダ式)を定義する必要がでてきます。

anything-c-symbolifyは、シンボルならばそのまま、文字列ならば対応するシンボルを返す変換関数です。 なぜ単純にinternではないかというと、文字列だけでなくシンボルも候補として認めているためです。


(define-anything-type-attribute 'function
'((action ;; 本当は describe-function と書きたい
("Describe function" . anything-c-describe-function)
("Add function to kill ring" . anything-c-kill-new)
;; 本当は find-function と書きたい
("Go to function's definition" . anything-c-find-function))
(action-transformer anything-c-transform-function-call-interactively)
(candidate-transformer anything-c-mark-interactive-functions))
"Function. (string or symbol)")
(defsubst anything-c-symbolify (str-or-sym)
"Get symbol of STR-OR-SYM."
(if (symbolp str-or-sym) str-or-sym (intern str-or-sym)))
(defun anything-c-describe-function (func)
"FUNC is symbol or string."
(describe-function (anything-c-symbolify func)))
(defun anything-c-find-function (func)
"FUNC is symbol or string."
(find-function (anything-c-symbolify func)))
導入後

そこで、coerce属性を導入することで、アクションに渡る直前に変換関数を通せます。 anything-c-describe-function、anything-c-find-functionはもう不要になりました。


(define-anything-type-attribute 'function
'((action ("Describe function" . describe-function) ; *
("Add function to kill ring" . anything-c-kill-new)
("Go to function's definition" . find-function)) ; *
(action-transformer anything-c-transform-function-call-interactively)
(candidate-transformer anything-c-mark-interactive-functions)
(coerce . anything-c-symbolify)) ; *
"Function. (string or symbol)")
display-to-real属性との違い

display-to-real属性は、表示文字列からアクションに渡すオブジェクトを切り出す関数です。 この関数は、候補選択時に呼ばれるものです。

対して、coerce属性は、アクション実行時に呼ばれます。 display-to-realとcoerceの双方を指定している場合は、display-to-realの結果がcoerceに渡されます。 アクションに渡す型をcoerce(強制)するのがcoerce属性の仕事です。

anything-marked-candidatesの結果はcoerce後のオブジェクトが返る

それに伴い、マークされた候補のリストを返すanything-marked-candidates関数は、型変換後のオブジェクトを返すようにしました。

アクション関数をマーク対応にするには、以下のように機械的変換で行えます。 つまり、元の関数をdolistで囲むのです。


;; 単数形
(lambda (candidate)
(some-action-function candidate))
;; 複数形
(lambda (ignore)
(dolist (candidate (anything-marked-candidates))
(some-action-function candidate)))

もし、anything-marked-candidatesが型変換後のオブジェクトを返さなければ、アクション関数は動作しなくなってしまいます。

セッションログ保存機能

anythingセッションで何が起きたのかを詳細にログを取れます。 anything.elデバッグをするのに便利です。

変数debug-on-errorあるいは anything-debug がtのとき、*Anything Log*バッファにログが蓄積されます。

ログをすべて保存する

anything-debug にディレクトリ名を指定することで、セッションごとのログがすべて保存されます。 anything-debugで指定したディレクトリ以下に日付ごとのディレクトリが作成され、その下でログは保存されます。

たとえば


(setq anything-debug "/log/anything")

と設定しているときに、 [2010/09/06 01:17:04] のログは /log/anything/20100906/20100906-011704 になります。

ログの容量は人によって異なりますが、一日あたり数十〜100MBあたりになります。 ディスク容量には気をつけてください。

最新のログを開く

最新のログファイルを開くには M-x anything-open-last-log を使います。 anythingの挙動がおかしいときは、すぐにこのコマンドを実行します。 ただし、このコマンドをanythingで実行すると、コマンド実行時のログが開いてしまうので、キーに割り当てておいてください。

anythingのバグだと感じた場合は、M-x anything-send-bug-reportでのバグレポートに、最後のログを貼り付けてください。

自分用のanything-type-attributesを定義する

define-anything-type-attributeの問題

型に対応する属性群(主にアクション)を定義するには、 define-anything-type-attribute 関数を使います。


(define-anything-type-attribute 型 属性群 説明文字列)

具体的にはこんな感じで使います。anything-config.el定義が書いていますが、やや簡略化しています。


(define-anything-type-attribute 'file
'((action
("Find file" . anything-find-many-files)
("Find file other window" . find-file-other-window)
("Find file other frame" . find-file-other-frame))
(persistent-help . "Show this file")
(action-transformer anything-c-transform-file-load-el
anything-c-transform-file-browse-url)
(candidate-transformer anything-c-w32-pathname-transformer
anything-c-skip-current-file
anything-c-skip-boring-files
anything-c-shorten-home-path))
"File name.")

anything-config.elは随時更新されているので、使えるアクションはどんどん増えていきます。 .emacsにdefine-anything-type-attributeを書くことで、自分好みの設定ができます。 しかし、それではanything-config.el の変更は反映されません。

anything-c-arrange-type-attributeで自分の設定とデフォルトの設定をマージする

anything-config.elの変更を反映しつつ、自分の設定を加えるためには、 anything-c-arrange-type-attribute 関数を使います。 使い方は define-anything-type-attribute に似通っています。


(anything-c-arrange-type-attribute 型 属性群)

属性群にRESTを入れると、デフォルトの設定をそこに加えます。 だぶっている要素は後ろの要素が取り除かれます。


(anything-c-arrange-type-attribute 'file
'((action ("Find file" . anything-find-many-files)
("Find file (emacs1 frame)" . display-file-in-emacs1-frame)
("Find file other window" . find-file-other-window)
REST)
(action-transformer anything-c-transform-file-media-file
REST)
(candidate-transformer anything-c-skip-current-file
anything-c-skip-boring-files)))

この設定で、デフォルトとマージされるので、以下の定義と同じになります。


(define-anything-type-attribute 'file
'((action
("Find file" . anything-find-many-files)
("Find file (emacs1 frame)" . display-file-in-emacs1-frame)
("Find file other window" . find-file-other-window)
("Find file other frame" . find-file-other-frame))
(persistent-help . "Show this file")
(action-transformer anything-c-transform-file-media-file
anything-c-transform-file-load-el
anything-c-transform-file-browse-url)
(candidate-transformer anything-c-skip-current-file
anything-c-skip-boring-files))
"File name.")

Known Bug: Windows環境だと絞り込みがとても遅くなる

最新版だと、Windows環境での絞り込みが遅くなる問題が確認されています。 しかし、僕はWindows環境を持っていないので修正するのが困難です。 anything-updateまわりの関数に原因がある気がします。 パッチ求む!