C-u 大事 - Emacs のキーバインドが枯渇気味の人へ -
だいたい Emacs 使ってて「だいたい使うなー」という拡張が決まってきた。それは良いんだけど、ちょこちょこ拡張を足そうとするときに使い勝手の良いキーバインドはだいたい埋まってきた気がする。
元々 Emacs それ自身が取ってしまっているのもあれば、メジャーモードとか Cider みたいな超多機能拡張がありとあらゆるキーバインドを持って行こうとする。それで何一つ重複させないのは至難の業だと思う。俗に言う Emacs のキーバインド枯渇 issue である。
話は少し変わるけど、最近 Emacs 拡張のコードをたまに読んだりすることがある。そうしているとあるコード辺がよく出てくることに気がついた。 (interactive "p") というコードである。
調べてみるとこのコード辺、前置引数を受け取ることが出来るということらしいけど、最初何の役に立つのか全く検討がつかなかった。更に調べると以下の記事を見つけた。
お陰でようやくこのキーバインド枯渇問題と向き合うことが出来た。とどのつまり簡単に書くなら C-u と押した回数分だけ 4 の倍数が前置引数として渡るので、コマンドの中でそれを元に実行するコマンドを分けてしまえばいいということのよう。例えば C-u C-x C-f みたいな入力をすると C-x C-f にバインドされているコマンドに対して 4 が渡る。
上記の記事に触発されて最近、僕もこれを多用していて使いやすいなーと感じる使い方が出来るようになってきたのでシェアしておこうと思った。
僕の場合は例えばこういう設定をしていたりする。
(bind-keys :map global-map ("C-x C-r" . helm-projectile-recentf) ("C-x b" . helm-projectile-switch-to-buffer) ("C-x C-f" . (lambda (arg) (interactive "p") (case arg (4 (helm-projectile-find-file)) (t (call-interactively 'find-file))))))
これは projectile を helm インターフェイスから使える helm-projectile という拡張を設定しているのだけど、 find-file はなんだかんだ使いやすいので変えたくないけど、ある条件化のときはプロジェクト配下にあるファイルを全て helm で検索したいので helm-projectile-find-file を使いたいというようなときに、こういう風に切り分けている。
もうひとつ紹介してみる。
(bind-keys :map ac-mode-map ("C-i" . (lambda (arg) (interactive "p") (case arg (4 (ac-complete-with-helm)) (t (auto-complete))))))
これもさっきと同じでデフォルトを素の auto-complete にしておいて、 helm インターフェイスを C-u を一度押した方に設定している。
と、まぁこんな感じで最近色々とキーバインドを増やせたこともあり、 Emacs から更に抜け出せなくなっていっている次第です。
余談
確かこれを簡単に実現出来る拡張を何処かで見たことがある気がするけど、忘れました。ただ、結局コードの量がそんなに増えたり減ったりするわけじゃなさそうだったので、僕はこれでいいやと思ってそのままにしています。