前回と違うキーが押されたなら通常の動作, 同じキーが押されたなら別の動作をさせる

意味不明なタイトルになってしまった.
どういうことかというと, 例えば, C-a に my-test という関数が割り当てられていたとする.
それで, my-test を起動し, 実行したあと, C-a 以外が押されたならば, 通常のキー入力と同じ動作をする.
a が押されたならば, 関数 self-insert-command が起動して a が入力される.
M-x ならば, execute-extended-command が実行される.
もし, C-a (関数に割り当てられているキーと同じキーが入力された)ならば, 別の動作をする.
このようなこと.



dabbrev-expand-multiple で, 最初に起動したときは,
通常の dabbrev-expand と同じで, もう一度 M-/ 押した場合は,
複数選択項目が出るようにしようと思って, テスト用の関数を作成してみた.
M-x からの起動も考慮して, 押したキーが M-/ の場合は必ず複数選択になるように作ってみた.


上手くできたバージョン.
# 見てわかると思うけど, 貼ってるのは作成したテスト関数.
たぶん, これで大丈夫なはず.

(global-set-key [(hyper t)] 'my-test)

(defun my-test ()
  (interactive)
  (let (action)
    (insert "test")
    ;; 何らかのキー入力を待ち, 押されたキーを記録
    (setq action (read-key-sequence-vector ""))
    (cond
     ;; この関数を起動するために使用したキーと同じキーが押された場合
     ((or (eq (aref action 0) last-command-char)
          ;; M-/ の場合も同様とする.
          (eq (aref action 0) (event-convert-list '(meta /))))
      (message "this is %s" action))
     ;; 入力したキーに割り当てられているコマンドを実行する
     (t (message "%s" (aref action 0))
        (let ((last-command-char (aref action 0))
              (command (key-binding action)))
          (when command
            (call-interactively command)))))))

これでたぶん, a, t, C-a, M-t, はたまた, H-t, s-2 とかでもいけるはず.
Hyper, Super でも上手くいくようにするのが大変やった.
Hyper, Super は, 自分が使ってるから無視できないw
このテスト関数は, Hyper-t に割り当てられている.
起動すると, test という文字列を挿入し, 他のキーの入力を待つ.
もし, Hyper-t や, M-/ ならば, "this is [キーの数字]" をミニバッファへ出力する.
それ以外のキーならば, 通常どおり使ったのと同様に処理される.
a を押せば, a が, b を押せば b が挿入される.
(self-insert-command を上書きしていなければ.)



これを作ってるときに別の方法でやろうとしたバージョン.
結局上手くいかなかった.

(defun my-test ()
  (interactive)
  (let (action)
    (insert "test")
    ;; 何らかのキー入力を待ち, 押されたキーを記録
    (setq action (read-key-sequence-vector ""))
    (cond
     ;; この関数を起動するために使用したキーと同じキーが押された場合
     ((eq (aref action 0) last-command-char) (message "this is %s" action))
     ;; マクロを使用して入力したキーに割り当てられているコマンドを実行する.
     ;; マクロを使った理由は, 他の方法では,
     ;; Hyper, Super に割り当てられているコマンドが上手く実行できなかったため.
     ;; 問題は, エラー処理. 割り当てられていないキーを入力した場合, どうするか.
     ;; M-x も駄目だ.
     (t (let* ((last-kbd-macro action)
               (kmacro-counter 0)
               (kmacro-counter-format "%d"))
          (kmacro-call-macro 1))))))

最初, Hyper とか Super で上手くいかなったから, マクロを使ってやろうとした.
これだと, M-x とかできなかったり,
何も関数が割り当てられていないキーが押されるとエラー吐いたりと散々な結果となった.


次は, 日本語変換みたいに補完候補のループの実装でも目指すかな.
# 最初掲示した補完候補3つに目的のものがなかったら, 次の3つを掲示するのような.
これができれば, dabbrev-expand と置き換えられる, かなあ?
まあ, まだまだ先のことやなw
X じゃなかったとき tooltip が(たぶん)使えなくなるだろうから必要になるであろう, インライン表示も実装できてねえし.



とりあえず, 今日はここまで.

更新時刻

2007年, 8月10日, 3:26