任意のメジャーモードでもone-key.elを利用してキーバインドを表示するone-key-local.elを作りました

これは何?

Emacsの壁のひとつにキーバインドがあるかと思います。
凡人では覚えきれない、その無数のキーバインドのヘルプを一覧で表示してくれる one-key.elという素晴らしい拡張があります(※1)。
ですが、以下のような不満を私は感じていました(※2)。

  • 設定が簡素化されているのはグローバルマップのみで特定のモードについては設定用のコードを結構書く必要がある
  • その設定用のコードを出力してくれる拡張もあるが、キーバインドを変更したら、設定用のコードも更新する必要がある
  • プレフィックスキー(連続したキーストローク)のキーバインドは、個別に設定を記述しなければならない

私としては、ときどき使うようなモードでこそone-key.elでメニューを表示したかったので、 何とかならないかとソースを眺めてみたところ、フックとアドバイスで解決できましたので公開することにしました。

スクリーンショット

Dired Modeのキーバインドを表示してみました。

f:id:aki2o:20130325065033p:plain

上記はpopwin.elを利用して、One Keyバッファをポップアップしています。

特徴

任意のmajor-mode、minor-modeでキーバインドが表示できる

例えば、hoge-modeのキーバインドを表示したいと思ったとき、 フックを持っている(hoge-mode-hookがある)か、モードを起動するコマンドがある(M-x hoge-mode ができる)なら、 おそらく大丈夫です。

連続したキーストロークのメニューも再帰的に自動生成する

one-key.elでは、"C-x r k"のような連続したキーストロークは"C-x"のメニューを生成しても表示されず、 事前に"C-x r"のメニューを生成した上で、"C-x"のメニューを生成する必要があります。 つまり、事前にキーバインドを調べた上で、表示したいキーマップについて、 より連続したキーストロークから順にメニューを生成する設定をしないといけないということです。 これは、ナマケモノな自分にはハードルが高かったので、 指定されたキーマップの中に存在する連続したキーストロークのマップも自動で生成するようにしました。 これで、キーバインドがたくさんあるモード(Org Modeとか)でも、 ルートに対して設定するだけで配下の全てのマップのメニューが生成できます。

有効になっているマイナーモードのキーバインドのメニューも自動生成する

あるモードでキーバインドを知りたいと思うとき、それは、そのモードで定義されているキーバインドだけでなく、 そのときに使える全てのキーバインドを知りたいと思うのが普通ではと思います。 なので、あるモードを指定したメニュー生成したとき、そのモードになったとき割り当てられている 全てのキーバインド(※3)についてメニューを生成しています(※4)。

インストール

ソース置場: https://github.com/aki2o/one-key-local

上記URLにアクセスし、one-key-local.elをダウンロードしてロードパスの通った場所に配置して下さい。 auto-install.elが利用できるなら、以下のs式を評価することでインストールできます。

(auto-install-from-url "https://raw.github.com/aki2o/one-key-local/master/one-key-local.el")

インストール後、.emacsまたはinit.elに以下を記述

(require 'one-key-local)

設定

目的のモードに対して、.emacsまたはinit.elに以下のように記述して下さい。

そのモードがフックを持っている場合

(one-key-local-create-menu :hook 'dired-mode-hook :key nil :bind "?")

フックがない場合(※5)

(one-key-local-create-menu :mode 'moccur-mode :key nil :bind "?")

マップ名がフックやモード名と連動していない場合

(one-key-local-create-menu :mode 'moccur-grep-mode :map 'moccur-mode-map :key nil :bind "?")

特定のキーマップだけメニュー表示

(one-key-local-create-menu :hook 'org-mode-hook :key "C-c C-x" :bind "C-c C-x")

引数について

  • hookまたはmodeは必ず指定して下さい
  • mapは未指定なら、hoge-modeやhoge-mode-hookが指定された場合、hoge-mode-mapとなります
  • keyはメニュー表示対象のプレフィックスキーのキーストロークです
  • keyがnilの場合、特定のプレフィックスキー配下でなく全てのキーバインドがメニュー表示対象になります
  • bindはメニュー表示を実行するキーストロークです
  • key、bindに指定する文字列は、(kbd "...")の...部分の文字列です

Enjoy!

その他

  • one-key.elが必要です。

※1 : その他にもone-key.elを特定のモード向けにした拡張もいくつかあるみたいです。
※2 : 使ってみて、ソースを見て、多分できないんじゃないかと。
※3 : グローバルマップは除外してます。必要ないかと(私は)思いました。
※4 : キーマップによっては再帰的に生成できないものがあります(原因不明)。もし、"[OneKeyLocal] Not yet create menu 'XXX' on ..."のようなメッセージが表示された場合は、XXXのメニューをまず生成するようにしてみて下さい。
※5 : modeに指定するシンボルは関数でないといけません。

リンク