anything-filelist 〜すべてのファイルを瞬時に開く方法〜

Emacs本を書きました


深いディレクトリ階層にあるファイルを開くのは面倒なものです。
比較的最近使ったファイル・よく使うファイルであればrecentfを使えば問題ありません。
もし、recentfに入っていないファイルの場合、長いパスを入力するなりlocateを使うなりしないといけません。
面倒ですね。


recentfは便利なのでここ参照


そこで、システム上のすべてのファイルをリストを作成して、そこから開く方法を使います。


anything.elをインストールする

まずは準備段階として、anything.elをインストールしておきましょう。


最新機能なのですでに入れている人は更新しておきましょう。
具体的には M-x auto-install-batch anything を実行するだけです。


http://d.hatena.ne.jp/rubikitch/20100718/anything


gitリポジトリを使う方法もあります。


git clone git://repo.or.cz/anything-config.git


ファイルリストを作成する

まずはファイルリストを作成する必要があります。


シンプルな方法

アルゴリズムはごくごくシンプルな方法です。
ファイルリストから複数個のgrepで絞り込んでheadで先頭200個を取り出すだけです。
この単純な方法であっても、現在のコンピュータは一瞬ではじきだしてくれます。
古いPentium4マシンでもコンマ数秒です。


anything-c-source-locateの置き換え

もともとこの目的には、locateコマンドを使うのが伝統的です。
updatedbコマンドでファイルリストを作成し、locateコマンドでファイル名を取り出す方法です。
anything.elでも anything-c-source-locate 情報源や anything-locate コマンドが使えます。
しかし、動作が遅い上、複数クエリによる絞り込みができないという最大の欠点があります。


ファイルリスト作成コマンド

ファイルリスト作成コマンドは find / の結果を保存する方法がありますが、これだと不要なファイルが含まれてしまいます。


ファイルリストの検索結果は上位200個のみを取り出すので、比較的よくアクセスするディレクトリを優先的に並べておく必要があります。
典型的にはホームディレクトリを優先します。
アクセス頻度を考えていない find / による方法だと、欲しいファイルが埋まってしまいます。


そこで、賢いファイルリストを作成するRubyスクリプトを作成しました。
以下からダウンロードして保存するか、gitリポジトリ上の extensions/make-filelist.rb を使ってください。


http://repo.or.cz/w/anything-config.git/blob_plain/master:/contrib/make-filelist.rb


以下のコマンドで、システム上のほぼすべてのファイル名を /tmp/all.filelist に保存します。
ホームディレクトリ→その他のディレクトリの順番で保存します。
また、.git等リストする必要のないファイルは除外されます(ack-grep準拠)。
(ほぼ)すべてのファイルをリストするため、root権限で実行します。



$ sudo ruby make-filelist.rb > /tmp/all.filelist




ファイルリストのカスタマイズ

ファイルリストはより細かくカスタマイズできます。
make-filelist.rbのCustomize Variablesの部分を ~/.make-filelist.rb にコピーし、好みにあうように設定してください。
~/.make-filelist.rb が存在するならば、読み込まれ、デフォルトの設定を上書きします。


僕は以下の内容にしています。


$EXCLUDE_PATH = %w[
. .. backup backup1 backup2 backup-system lost+found tmp temp rubikitch.lost
.cache w3mtmp proxy-cache trash proc RCS.old
autom4te.cache blib _build .bzr .cdv cover_db CVS _darcs ~.dep ~.dot .git .hg ~.nib .pc ~.plst RCS SCCS _sgbak .svn
]

# Exclude regexps (backup files, core files, and so on)
$EXCLUDE_REGEXP = Regexp.union(/~$/, /\#.+\#$/, /[._].*\.swp$/, /core\.\d+$/, # from ack-grep
/\.(?:elc|o)$/, /,v$/)

# Set default directories to collect
$LS_DIRS = [
"~/emacs/init.d", "~/emacs/lisp", "~/.emacs.d", "~/emacs",
"~/gdgd", "~/memo", "~/book", "~/src", "~/public_html", "~/private_html", "~",
"/m/usr/share/emacs/23.1.50", "/m/usr/share/emacs/site-lisp", "/m/log/emacswikipages",
"/m/home/local/lib/ruby19", "/m/home/local/lib/ruby", "/m/log/compile/ruby19", "/m/log/compile/ruby18",
"/m/log/compile", "/m/log", "/m/home/local", "/m/home/nobackup",
"/m/usr", "/etc", "/m/home/archives", "/m/l/var",
"/"
]




また、make-filelist.rbの引数に1つ以上のディレクトリを指定することで、そのディレクトリのみのファイルリストを作成できます。



$ ruby make-filelist.rb ~ /etc > ~/partial.filelist





設定



cronでファイルリストを自動更新する

ファイルリストが古いままだと、新規ファイルが反映されないので、rootのcronで自動更新しておきましょう。
crontabに以下の行を加えると、1:00に実行します。


0 1 * * * ruby /path/to/make-filelist.rb > /tmp/all.filelist




.emacsに加える設定

.emacsでは、ファイルリストのファイル名を指定しておけばよいです。
高速に動作させるためには、ファイルリストはRAMディスクやtmpfsに置いておきましょう。
そして anything-grep-candidates-fast-directory-regexp にそのディレクトリの正規表現を指定しておきましょう。


(require 'anything-startup)
(setq anything-c-filelist-file-name "/tmp/all.filelist")
(setq anything-grep-candidates-fast-directory-regexp "^/tmp")
^#+ENDSRC


使い方

それではさっそく使ってみましょう。
コマンドとして M-x anything-filelist、 M-x anything-filelist+ を用意しています。
情報源の変数はanything-c-source-filelistです。


M-x anything-filelist

M-x anything-filelistを実行し、4文字以上入力すればマッチするファイル名を取り出してくれます。
もちろん、スペース区切りによる絞り込みもできます。


http://www.rubyist.net/~rubikitch/archive/anything-filelist.png


M-x anything-filelist+

anything的には、ファイルリストだけではなくて、バッファや最近使ったファイルからも開くようにしておきましょう。
M-x anything-filelist+ は以下の情報源を使っています。


  • カーソル位置のファイル

  • バッファ

  • 最近使ったファイル

  • ブックマーク

  • ファイルキャッシュ

  • ファイルリスト


M-x anything-for-files の高速版です。


新規ファイルを開く

実は、これを使って新規ファイルを開くこともできます。
あまり知られていませんが、選択した候補がファイル名のときにC-x C-fを押すと、そのディレクトリからファイルを開くようになります。
たとえば、 comm とパターンを入力して、 ~/emacs/lisp/sequential-command.el にカーソルがあるときにC-x C-fを押すと、~/emacs/lisp/からファイルを開く準備をします。
これにより、特定ファイルの存在するディレクトリに新規ファイルを作成することが簡単にできます。
これはファイルリストの機能ではなくて、anything.el本体の機能です。



2012-01-03 火日本語には対応していません

anything-filelistは残念ながら日本語のファイル名やmigemoには対応していません。


また、nkfRuby組み込みなので、
ruby /path/to/make-filelist.rb | ruby -rkconv -e 'puts ARGF.read.tosjis' > /tmp/all.filelist
でもいけますね。