define-key や global-set-key をまとめる
せっかくブログを作ったので、ちょっとした小ネタを。
キーバインドを設定する
emacs をカスタマイズするにあたって、キーバインドを設定/変更することは多いかと思います。
新しくインストールしたパッケージのコマンドを押しやすいところに割り当てたり、
システムのショートカットキーと統一してみたり、
はたまた vi 風のキーバインドにしてみたり。
キーバインドはテキストエディタにとって重要なので、
デフォルトのキーバインドを大きく改変したり、
あーでもない、こーでもないと色々と悩んだりすることもあると思います。
結果として .emacs にこんな感じのコードが出来上がります。
(これは僕の .emacs の一部です…)
;; hjklをカーソル移動に (define-key image-mode-map (kbd "h") 'image-backward-hscroll) (define-key image-mode-map (kbd "j") 'image-next-line) (define-key image-mode-map (kbd "k") 'image-previous-line) (define-key image-mode-map (kbd "l") 'image-forward-hscroll)
define-key いっぱい…
何でも自動化してしまうはずの emacs なのに、
何だこのコピペした感じのコード、なんだかかっこ悪い…
きっと書き手も読み手もこんな感じに見えているんじゃないかと思います。
;; hjklをカーソル移動に (define-key image-mode-map (kbd "h") 'image-backward-hscroll) (... ... (kbd "j") 'image-next-line) (... ... (kbd "k") 'image-previous-line) (... ... (kbd "l") 'image-forward-hscroll)
マクロで繰り返しから逃げる
せっかくマクロが使えるので、まとめてしまいましょう!
(defmacro define-keys (mode-map &rest body) "特定のキーマップをまとめて設定する。 ;; 改善前 (define-key any-mode-map (kbd \"C-x\") 'any-function) (define-key any-mode-map (kbd \"M-a\") 'hoge-function) ;; 改善後 (define-keys any-mode-map ((kbd \"C-x\") 'any-function) ((kbd \"M-a\") 'hoge-function)) " `(progn ,@(mapcar #'(lambda (arg) `(define-key ,mode-map ,@arg)) body))) ;; global-set-keyの複数版。 (defmacro global-set-keys (&rest body) "`global-set-key'をまとめて設定する。 詳細については`define-keys'を参照。" `(progn ,@(mapcar #'(lambda (arg) `(global-set-key ,@arg)) body)))
こんな感じのマクロを用意することで、先ほどの同じようなコードの繰り返しを回避できます。
おまけで、global-set-key でも同じことが出来るようにしておきました。
マクロ名はすごく適当なので、適宜変えてください。
簡単に名前が被りそうなので…
これで、最初に示したコードは次のようになります。
;; hjklをカーソル移動に (define-keys image-mode-map ((kbd "h") 'image-backward-hscroll) ((kbd "j") 'image-next-line) ((kbd "k") 'image-previous-line) ((kbd "l") 'image-forward-hscroll))
結構すっきりしたんじゃないでしょうか。
これで、同じようなコードを見る機会が減らせそうですね。
こんな感じで emacs をカスタマイズして、カスタマイズするための emacs-lisp を書いて、
なんてやっているとすぐに時間がなくなってしまいますね。