init.el編集後、Emacsを再起動できない!?
Emacsのinit.elを編集したあとEmacsを終了し、正常に起動できなくなってしまい困った経験はないでしょうか。
私はたくさんあります。編集しなおそうにも肝心のEmacsが思い通りに動いてくれないわけで、イライラと悲しみをかかえながら問題を解決することになるわけです。
こうした事態を避けるため、init.elを編集したあとはbyte-compile
をするとか、
eval-buffer
をするとかして、早めにエラー検出するよう心がけていました。それでも起動できなくなることは多くありました。
eval-bufferなどで文法エラーなどは検出できるものの、必要なライブラリを読み込めてなかったり、ライブラリの仕様が変わったりしてエラーになることが多かったのです。特に、自作ライブラリを使ったりしているとそうした問題がよく発生します。
ソフトウェアテストでは、まっさらな環境を準備するのが大切と言われます。
init.elをテストする場合も、やはりまっさらな環境でテストすることが必要なわけです。
スモークテスト
さて、ソフトウェアテストには「スモークテスト」と呼ばれるものがあります。もともとは、「水道管に煙を流し込んで漏れがないかをチェック」「ハードウェア製品/部品に電源を投入し、煙が出たり発火したりしないことを確認する」という意味だったそうで、ソフトウェアの世界では、とりあえず実行ができるかどうかを試すテストの意味で使われます。
詳しくは、ITmrdiaの「情報システム用語事典」やWEBサービスソリューションHeartsNの用語集などを参照して下さい。マイクロソフト社のドキュメントによれば、「コードを見直した後にソフトウェアの不具合を確認し修正する作業として、スモーク テストは最も費用効率の高い方法」だそうです。このスモークテストをinit.elに対して適用できないか、ということを考えました。
init.elのスモークテスト
- init.elで最終行に特定の文字列、たとえば"End of loading init.el."を出力するようにする
- Emacsをバッチモードで実行し、init.elを読み込ませ、すぐに終了する
この手順でバッチモードのEmacsから、最終行が正しく出力されるかチェックすれば、まっさらな環境でinit.elの動作を確認できるはずです。
では、実際にやってみます。
最終行で "End of loading init.el."を出力
最終行で "End of loading init.el."を出力するには、init.elの最後の行に次の1行を追加します。
(message "End of loading init.el.")
Emacs Lispのmessage関数は、ヘルプに記載されているように、指定されたメッセージを通常は画面下部に表示し、*Messages*バッファに出力します。バッチモードでは、標準エラーに出力されるので、バッチモード時のメッセージの確認にも適した関数です。
Emacsをバッチモードで実行
M-!で、shell-commandを呼び出し、次のコマンドを実行します。
emacs -batch -l ~/.emacs.d/init.el 2>&1
すると、*Shell Command Output*バッファにinit.elを読み込んだときのメッセージが出力されています。このバッファの最終行に"End of loading init.el."が出力されていれば、init.elは最後まで読み込まれたことになります。
出力されるメッセージが多く、最終行の確認が面倒な場合、LinuxやMacでは次のコマンドを実行すればいいでしょう。
emacs -batch -l ~/.emacs.d/init.el 2>&1 | tail -1
emacsの出力結果をパイプでtailコマンドに渡して、最終行だけを表示します。Emacs画面下部のミニバッファにEnd of loading init.el.
が表示されていれば、init.elが最後まで読み込まれたことになります。異なるメッセージが表示される場合は、init.elの記述が正しいかを確認すべきです。
また、teeコマンドを使って次のコマンドを実行すると、実行ログをmessage.logファイルに保存しながら、スモークテストを実行できます。
emacs -batch -l ~/.emacs.d/init.el 2>&1 | tee message.log | tail -1
繰り返しテストするために
こうしたスモークテストは、init.elなどを修正するたびに行うべきです。そのためには、簡単な手順で実行でき、結果もわかりやすく確認できるのが望ましいです。
私は、自作のテストフレームワークAutotest.mkを使い、init.elのあるディレクトリーでmakeを用いたmake check
を実行すれば、スモークテストを実行できるようにしています。Emacsでは、makeを用いたコマンドはcompile
というコマンドから実行すると便利です。
ほかに、EmacsのテストフレームワークであるERTを使って、スモークテストを実行するコマンドを作ってもいいかもしれません。
まとめ
init.elをスモークテストする仕組みを作れば、Emacsを再起動できなくなって悲しい思いをすることが少なくなります。