key-chordを書いてみた。

emacsにはkey-chord.elなる便利なものがあるらしい。2キー同時押しでコマンドを起動できるとか。key-chord.lはまだ誰も書いてないのか、見つからないのでちょっと書いてみた。

(defvar *key-chord-map* nil)
(defvar *key-chord-interval* 20)

(defun key-chord ()
  "2つ同時押しとか"
  (let ((time (get-internal-real-time))
    (a (svref (get-recent-keys) (1- (length (get-recent-keys)))))
    c cmd)
  (while (not (or (setq c (read-char-no-hang *keyboard*))
          (> (- (get-internal-real-time) time) *key-chord-interval*))))
  (and a c
     (setq cmd (find-combination (list a c) *key-chord-map* :prd 'char< :test 'equal :key 'car))
     (setq *this-command* (cadr cmd)))
  (if (and (not cmd) c) (progn (unread-char c) (refresh-screen)))))

(defun find-combination (keys sorted-lst &key (prd '<) (test 'equal) (key 'identity))
  (find (stable-sort keys prd) sorted-lst :test test :key key))

(defun define-key-chord (keys cmd)
  (unless (find-combination #1=(list (car keys) (cadr keys)) *key-chord-map* :prd 'char< :test 'equal :key 'car)
	(push (list (stable-sort #1# 'char<) cmd)
			 *key-chord-map*)))

(add-hook '*pre-command-hook* 'key-chord)

これだけ。全部評価して、(define-key-chord '(#\f #\j) 'kill-line)とか登録すれば使える。ただ、適当に作ったので動作がもっさりしてしまう。*key-chord-interval*を小さくすれば気にならないけど、そのかわり反応が悪くなる。とりあえず書いたから誰か調整してくれないかなあ。