キーテスト用のマイナーモード

 2chの流れで色々自分で、キーを試してたら段々何度も再起動したり設定したりしてるのが面倒になってきたので、キーテスト用のモードを適当に書いてみた。
 前に書いてたtester-key-settingとか言うのがあるんだけど、これでキーテストしていると、テストの後にテストしたキーマップを全部消したかったりして、xyzzyを再起動しないと駄目だったのが非常に面倒だったから。これをマイナーモードにしてみた。つまり、マイナーモードから抜ければ別にxyzzyを再起動しなくても普段のキー設定にできる感じに。後、設定を色々やってたらグチャグチャになってしまった時にxyzzy再起動しなくて言いようにkeymapをマイナーモードのキーマップをクリアに出来るようにとかしてみた。後は2ストロークも試せるようにして、コメントで色々教えてもらったのを参考少しコードを変えたりした。
キー割り当てをテスト - himadatenodeの日記
http://d.hatena.ne.jp/himadatanode/20070322/p1

■具体的にすること
 何の機能もないマイナーモードのキーマップに一時的に機能を割り当てたり、キーマップを空にしたりする。xyzzyを終了するとキー設定も消える。

■適当な使い方。
 .xyzzyとかに適当に書い て設定したら

M-x test-key-setting

とやると、"command name :"とミニバッファに出るので、設定するコマンドの名前を打ち込む*1。次に"set-key :"と出るので、そこで設定したいキーを打つ。後はEnter押したらyes or noを聞いてくるので、"y"を押すと設定される。2ストロークに設定したい時はEnter押さずに、続けて2つ目のキーを押す。
 キー設定を全部初期の状態に戻したい時は

M-x clear-test-keymap

 マイナーモードは抜けて、何時ものキー入力に戻る時は

M-x key-test-mode

でモードをトグルしてoffに。このモードで設定したキーバインドは再起動すると全部なくなってるので、気にせず適当に設定しても問題ない。

;; var
(defvar-local *key-test-mode* nil)
(defvar *key-test-setting* nil)

;; keymap
(defvar *key-test-mode-keymap* nil)
(unless *key-test-mode-keymap*
  (setq *key-test-mode-keymap* (make-sparse-keymap))
  (define-key *key-test-mode-keymap* #\C-g 'quit))

;; mode
(defun key-test-mode(&optional (arg nil sv))
  "key-testモードの呼び出し"
  (interactive)
  (ed::toggle-mode '*key-test-mode* arg sv)
  (update-mode-line t)
  (if *key-test-mode*
	  (set-minor-mode-map *key-test-mode-keymap*)
	(unset-minor-mode-map *key-test-mode-keymap*))
  t)

;mode line str
(pushnew '(*key-test-mode* . "key-test") *minor-mode-alist* :key #'car)

(defun test-key-setting()
  "キー設定を一時期的にする。xyzzyを再起動させれば設定は消える。"
  (interactive)
  (let* ((fun (read-command-name "command name :"))
		(key1 (ed::interactive-read-key-sequence "set-key :"))
		(key2 (ed::interactive-read-key-sequence
			   (format nil "set-key : ~S" (car key1)))))
	(if (not (char-equal #\RET (car key2)))
		(setq key1 (append key1 key2 )))
	(when (y-or-n-p "set-key:~S current-command:[~A]"
					key1 (lookup-key-command key1))
	  (define-key *key-test-mode-keymap* key1 fun)
	  (push key1 *key-test-setting*)
	  (clear-minibuffer-message)
	  (unless *key-test-mode*
		(key-test-mode t))
	  (message "test key set: ~S ~A" key1 fun))))

(defun clear-test-keymap()
  "テストモードのキーをクリアする"
  (interactive)
  (when (dolist (key *key-test-setting* result)
		  (setq result (undefine-key *key-test-mode-keymap* key)))
	(message "clear test keymap")))

 前の奴を見ると、ウィザード風にxyzzyでのキー設定機能とか思ってたようだけど、すっかり忘れていた。というか、頻繁に変えたりするのが多いテスト用とかじゃないのなら.xyzzyを直接書いたほうが早いような気もしてみたので、前のはスルーすることに。

 本当は"C-g"とかESCとか慣習的に設定しない方がいいキーの場所では何か警告くらい出るようにしても言いかなぁとか思ったりもしたけど。慣習を調べるのが大変そうだったので止めた。後、AAのキーボードの絵とかどこかで拾ったら一覧でキーバインド表示する奴とかかも付け足すかも。どのキーが空いているのか調べるのが面倒だなぁとか最近思ってるけどキーボードのアスキーアートが難しくて上手くかけないので、今の所なかったことに。

■追記
typoを修正

*1:ミニバッファでの補完とか履歴も普通に動いてるみたい