知らないと損するミニバッファ保険

Emacsを使ってて怖いことのひとつは、ミニバッファに入力中にC-gを押してしまうことだ。すると、今までの入力がパーになってしまう。
俺はskkを使っていて、変換をキャンセルするときにC-gを押すのだが、押しすぎたりタイミングを間違えたらミニバッファ入力がキャンセルされてしまう。なので、ミニバッファに日本語を打つときはいつも冷や冷やしていた。
以下の設定を加えると、C-gを押したときに現在の入力がヒストリーに記録されるようになる。間違ってC-gを押してしまった場合は、再び同じコマンドを起動してM-pで前の入力を呼び戻せるぞ。

(defadvice abort-recursive-edit (before minibuffer-save activate)
  (when (eq (selected-window) (active-minibuffer-window))
    (add-to-history minibuffer-history-variable (minibuffer-contents))))

ちなみに、ミニバッファのキャンセルはkeyboard-quitではなくてabort-recursive-editである。keyboard-quitはglobal-mapのC-gに定義されていて、minibuffer-local-mapではabort-recursive-editである。ミニバッファ内でC-h c (describe-key)してみれば調べられるし、以下の式の値からもわかる。

(assq ?\C-g minibuffer-local-map) ; => (7 . abort-recursive-edit)

ミニバッファは再帰編集で実装されている。そもそも再帰編集とは、コマンド実行中に任意の編集をする機能だ。なので、再帰編集を終えたら、元のコマンドへと制御が戻る。ミニバッファ入力はミニバッファを使うコマンドの途中で行われるものなので、再帰編集が使われているのは納得いくだろう。