mozc.elで無変換キー/全角半角キーでちゃんとmozc-modeを切る

linux用のmozcにはいつの間にかmozc.elがつくようになっている。これはC-\で切り替える分には困らないのだけど、僕はいつも変換/無変換キーをそれぞれ日本語入力on/offにわりあてており、今回もそれをやろうとしたら素直には行かなかったのでメモ。
最終的な.emacsの設定は以下のようになる。

    (set-language-environment "Japanese")
    (require 'mozc)  ; or (load-file "/path/to/mozc.el")
    (setq default-input-method "japanese-mozc")
    (progn ;toggle input method
      (define-key global-map [henkan]
	(lambda ()
	  (interactive)
	  (if current-input-method (inactivate-input-method))
	  (toggle-input-method)))
      ;; (define-key global-map [muhenkan]
      ;;   (lambda ()
      ;;     (interactive)
      ;;     (inactivate-input-method)))
      (define-key global-map [zenkaku-hankaku]
	(lambda ()
	  (interactive)
	  (toggle-input-method)))

      (defadvice mozc-handle-event (around intercept-keys (event))
	"Intercept keys muhenkan and zenkaku-hankaku, before passing keys to mozc-server (which the function mozc-handle-event does), to properly disable mozc-mode."
	(if (member event (list 'zenkaku-hankaku 'muhenkan))
	    (progn
	      (mozc-clean-up-session)
	      (toggle-input-method))
	  (progn ;(message "%s" event) ;debug
	    ad-do-it)))
      (ad-activate 'mozc-handle-event))

progn内のところがキーを切り替えるところ。
mozc-modeのキーマップmozc-mode-mapをみるとC-\だけがmozc-modeを切るのに使われていて、それ以外のキーイベントはすべてmozc-handle-event関数経由でmozcサーバに投げられる*1。mozc-mode-mapをいじるのは気が引けたのでここではmozc-handle-eventをadviceでくるんでzenkaku-hankakuとmuhenkanキーのみをインターセプトしてmozc-modeを切ってしまうようにした。advice便利ですね。
参考
GNU Emacs Lispリファレンスマニュアル: 16. Emacs Lisp関数のアドバイス

*1:のでglobal-set-keyではうまくいかない