巷で話題の anything.el を使ってみた
rubikitch さんのブログで anything.el というのを知った(*)のでここでも紹介します。劣化記事にならないようにがんばります。
(*) http://d.hatena.ne.jp/rubikitch/20070725#1186048100 (とても良いブログです)
anything.el って何?
「open anything」できるようになるらしいのですが、少し抽象的で分かりづらいと思います。簡単に言えば、複数の機能をひとつのインターフェースに統合してしまうということです。例えば、 M-x anything RET emacs と入力すれば、 find-file の候補として ~/.emacs 、 Info の候補として Emacs などが列挙され、さらに絞りこんだり、十字キーで直接選択して実際の機能を利用したりします。
動作原理
antyhing は入力されたパターンと anything-sources に定義されている複数の機能を使ってインクリメンタルに候補を生成します。つまり文字を入力してパターンを更新するたびに新しい候補が出てくるのです。 anything-sources は基本的に名前と候補関数のリストで構成されており、具体的な機能は候補関数として任意に定義させることにより anything の汎用的と拡張性を実現しています。
以下の例はバッファリストの選択機能を実装しています。
機能定義の例 (anything-config.el より抜粋 ):
(defun anything-c-buffer-list () "Return the list of names of buffers with the `anything-buffer' and hidden buffers filtered out. The first buffer in the list will be the last recently used buffer that is not the current buffer." (let ((buffers (remove-if (lambda (name) (or (equal name anything-buffer) (eq ?\ (aref name 0)))) (mapcar 'buffer-name (buffer-list))))) (append (cdr buffers) (list (car buffers))))) (defvar anything-c-source-buffers '((name . "Buffers") (candidates . anything-c-buffer-list) (volatile) (type . buffer))) (setq anything-sources (list anything-c-source-buffers))
インストール
以下の URL から anything.el と anything-config.el をダウンロードして load-path の通ったところにインストールします。
http://www.emacswiki.org/cgi-bin/wiki/download/anything.el
http://www.emacswiki.org/cgi-bin/wiki/download/anything-config.el
Gentoo の場合は僕の Overlay を利用すれば以下のようにインストールできます(たぶん普通にインストールするほうが楽です)。
% layman -f -o http://gentoo.panicode.com/layman.txt -a panicode % echo '=app-emacs/anything-9999 **' >> /etc/portage/package.keywords % echo '=app-emacs/anything-config-9999 **' >> /etc/portage/package.keywords % emerge anything anything-config
インストールしたら ~/.emacs に以下の設定を書きましょう。
(require 'anything-config)
ちなみに anything.el はコアの実装、 anything-config.el は良く使う機能の定義をまとめたものになっています。バージョンすらない開発途上の elisp なのでやさしく扱ってやってください。僕の環境では問題なかったのですが、知人の環境ではいきなり動かなかったそうです。そういう場合は作者に報告するかバグを潰してあげてください。ちなみに Emacs 22 じゃないと動作しないようです。
設定
anything-config.el には現時点で以下の機能が実装されています。
- anything-c-source-buffers
- バッファ選択機能を提供します。
- anything-c-source-file-name-history
- ファイル名履歴から find-file する機能を提供します。
- anything-c-source-recentf
- recentf を使って file-file する機能を提供します。
- anything-c-source-files-in-current-dir
- カレントディレクトリにあるファイルを find-file する機能を提供します。
- anything-c-source-source-man-pages
- man ページを閲覧する機能を提供します。
- anything-c-source-info-pages
- info ページを閲覧する機能を提供します。
- anything-c-source-complex-command-history
- コマンド履歴を選択してその SEXP を実行する機能を提供します。
- anything-c-source-emacs-commands
- Emacs のコマンド (M-x) を呼び出す機能を提供します。
- anything-c-source-emacs-functions
- Emacs の関数を呼び出す機能を提供します。
- anything-c-source-emacs-functions-with-abbrevs
- bb => bury-buffer や std => switch-to-buffer のように略語で Emacs の関数を呼び出す機能を提供します。
- anything-c-soruce-bookmarks
- ブックマークを選択して開く機能を提供します。
- anything-c-source-picklist
- picklist って何でしょうか、ごめんなさいわかりません。
- anything-c-source-imenu
- imenu 使ったことないです、ごめんなさい。
- anything-c-source-file-cache
- file-cache の機能を使って find-file する機能を提供します。
- anything-c-source-locate
- locate プログラムを使って find-file する機能を提供します。
- anything-c-source-tracker-search
- tracker-search というプログラムを使ってデスクトトップサーチする機能らしいです。よくわかりません。
- anything-c-source-mac-spotlight
- Mac の Spotlight を使って find-file する機能を提供します。
- anything-c-source-bbdb
- BBDB って何でしょうか、ごめんなさいわかりません。
- anything-c-source-evaluation-result
- 候補に使用されるパターンを eval した結果を表示する機能を提供します。
- anything-c-source-calculation-result
- 候補に使用されるパターンを calc-eval した結果を表示する機能を提供します。
- anything-c-source-google-suggest
- Google Suggest を使った Google 検索機能を提供します。
- anything-c-source-jabber-contacts
- jabber のコンタクトが表示されるようです。
個人的には anything-c-source-locate と anything-c-source-calculation-result と anything-c-source-google-suggest が面白いと思います。特に anything-c-source-calculation-result と anything-c-source-google-sugget は anything の力は find-file のみに限られないことを示す良い例だと思います。
それぞれスクリーンショットを貼ります。
デフォルトでは anything-sources は以下のような定義になっています。
(setq anything-sources (list anything-c-source-buffers anything-c-source-file-name-history anything-c-source-info-pages anything-c-source-man-pages anything-c-source-locate anything-c-source-emacs-commands))
僕は以下のように定義してみました。
(setq anything-sources (list anything-c-source-buffers anything-c-source-bookmarks anything-c-source-file-name-history anything-c-source-man-pages anything-c-source-info-pages anything-c-source-calculation-result anything-c-source-locate))
キーバインドは C-x b に割りあてるのが良いと思います。僕は C-x ; を iswitchb-buffer に割りあててるので実質 C-x b を使わないのです。
(global-set-key "\C-xb" 'anything) (global-set-key [?\C-;] 'iswitchb-buffer) (iswitchb-mode) (anything-iswitchb-setup)
window-system を利用していない人は C-x ; が使えないので C-x b への割りあては考えたほうがいいかもしれません。
最後に拙作の plocate (*) を anything から使えるように設定してみます(機能自体は locate に似ているので anything-c-source-locate をパクりました)。
(*) http://code.google.com/p/plocate/
(defvar anything-c-source-plocate '((name . "Personal Locate") (candidates . (lambda () (apply 'start-process "plocate-process" nil (list "plocate" "-p" "-r" anything-pattern)))) (type . file) (requires-pattern . 3) (delayed))) (setq anything-sources (list anything-c-source-buffers anything-c-source-bookmarks anything-c-source-file-name-history anything-c-source-man-pages anything-c-source-info-pages anything-c-source-calculation-result anything-c-source-plocate anything-c-source-locate))
ホームディレクトリに DB を構築しておきます。
% cd ~ % plocate -U -e .svn # .svn がうざいので排除しつつ構築
anything-default-directory がホームディレクトリ以下ならホームディレクトリに限定した locate のような動きになります。 locate はシステム全体にやるので早くても結果が返ってくるまで 2, 3 秒かかるのに対して、 plocate の場合は(今回の場合だと)ホームディレクトリ限定なので一瞬で結果が返ってきます。
とりあえず僕はこんな感じの設定で早速使いはじめています。これからいろいろ発見があると思うので引き続きブログに紹介していきたいと思います。
考察
Emacs ができて 20 年以上たっているのに、 anything のような飛躍的な機能改善がぴょこんと出てくるから Emacs はやめられない。今回 anything を使ってみて思った問題点を並べておきます。
- 候補数を絞るのが難しい(特に locate )
- 機能ごとの次と前がない
- 結構重い
多少重複している部分もありますが、おそらく今後の課題は以下に情報を絞るかといかに操作しやすくするかになると思います。また anything にはまだまだ未発見の拡張が隠されているはずです。特筆すべきはアクションは find-file に限らないということです。例えば locate を駆使して #include を挿入する機能を anything で実装したり、などです。僕もいろいろアイデアを出して実装してみたいと思います。ああ幸せ。
追記
とりあえず Occur と Semantic(*) を anything から使えるようにしてみた。 6 時間かかりました。普段から Elisp やってないとダメですね。
(*) http://cedet.sourceforge.net/semantic.shtml
まず Occur の anything 版。
ソースはこんな感じ。
(defvar anything-c-source-occur '((name . "Occur") (init . (lambda () (setq anything-c-source-occur-current-buffer (current-buffer)))) (candidates . (lambda () (setq anything-occur-buf (get-buffer-create "*Anything Occur*")) (with-current-buffer anything-occur-buf (erase-buffer) (let ((count (occur-engine anything-pattern (list anything-c-source-occur-current-buffer) anything-occur-buf list-matching-lines-default-context-lines nil list-matching-lines-buffer-name-face nil list-matching-lines-face (not (eq occur-excluded-properties t))))) (when (> count 0) (let ((lines (split-string (buffer-string) "\n" t))) (cdr lines))))))) (action . (("Goto line" . (lambda (candidate) (goto-line (string-to-number candidate) anything-c-source-occur-current-buffer))))) (requires-pattern . 3) (volatile)))
次は Semantic を使った移動機能。通常 Speedbar から Semantic を使って関数とかクラスに飛ぶのですが、 Speedbar は邪魔だし操作が煩雑なので anything で使えたほういいでしょう。
ソースはこんな感じ。
(defun anything-c-source-semantic-construct-candidates (tags depth) (apply 'append (mapcar '(lambda (tag) (when (and (listp tag) (or (equal (semantic-tag-type tag) "class") (eq (semantic-tag-class tag) 'function))) (cons (cons (concat (make-string (* depth 2) ?\s) (semantic-format-tag-summarize tag nil t)) tag) (anything-c-source-semantic-construct-candidates (semantic-tag-components tag) (1+ depth))))) tags))) (defvar anything-c-source-semantic '((name . "Semantic Tags") (init . (lambda () (setq anything-c-source-semantic-candidates (anything-c-source-semantic-construct-candidates (semantic-fetch-tags) 0)))) (candidates . (lambda () (mapcar 'car anything-c-source-semantic-candidates))) (action . (("Goto tag" . (lambda (candidate) (let ((tag (cdr (assoc candidate anything-c-source-semantic-candidates)))) (semantic-go-to-tag tag))))))))
これからもいろいろ実装していきたいと思います。
さらに追記
rubikitch さんからツッコミ (*) をいただいたので修正。どうもありがとうございます。
(*) http://d.hatena.ne.jp/rubikitch/20071009#1191903266
まず機能の次と前がないという話。 anything-next-source と anything-previous-source がまさにそれでした。以下のように設定しておきました。
(define-key anything-map (kbd "C-M-n") 'anything-next-source) (define-key anything-map (kbd "C-M-p") 'anything-previous-source)
機能をしぼるのが難しいという話。 rubikitch さんのように locate/updatedb を駆使してホームディレクトリにファイルパスのデータベースを作るのはいい方法だと思います。ていうか updatedb って findoption 渡せるんだ。 slocate の updatedb だとその手のオプション全然うけつけないから plocate なんていうもの作ってしまったよ。 Gentoo だと GNU findutils をインストールしても locate/updatedb がインストールされないので自分で入れないとダメっぽいです。
最後重いという話。重いけど delayed とか anything-sources の量を適切にしてやれば特に問題ないみたい。もちろん今後は大量の anything-sources からも簡単に絞りこめて、かつ速いというのを目指すのだろうけど。
- Category(s)
- emacs
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/matsuyama/open-anything-emacs/tbping
Re:巷で話題の anything.el を使ってみた
ところで私も「重さ」の点が気になって、delayed を付けたり volatile を外したり
(キャッシュの効果で若干速くなります)、anything-source-filter を設定したり
色々試したんですが、こんな方法に気付きました。
(defadvice anything-check-minibuffer-input (around sit-for activate)
(if (sit-for anything-idle-delay t)
ad-do-it))
つまり、現状だと1文字入力する度に anything バッファの再描画が行われてしまって
いて、これが重さの大きな要因だと思うんです。この変更で、検索文字列を入力し終わっ
てから描画してくれるようになります。どうでしょう?
Re:巷で話題の anything.el を使ってみた
コメントありがとうございます。