2016/05/13

Emacs で日本語を保存しようとすると "undecided-unix cannot encode" というエラーが出るようになったので修正してみた

日本語のメッセージ保存でエラー

私は Git のエディタとして Emacs を使用しています。
つい最近まで問題なく使用していたのですが、ここ最近、日本語(マルチバイト)のメッセージを保存しようとすると以下のようなエラーが出るようになってしまいました。
都度、コーディングシステムを指定すれば保存は出来るのですが、不便なので原因を探ってみました。

These default coding systems were tried to encode text
in the buffer `COMMIT_EDITMSG':
  (undecided-unix (1 . 12486) (2 . 12473) (3 . 12488))
However, each of them encountered characters it couldn't encode:
  undecided-unix cannot encode these: テ ス ト

Click on a character (or switch to this window by `C-x o'
and select the characters by RET) to jump to the place it appears,
where `C-u C-x =' will give information about it.

Select one of the safe coding systems listed below,
or cancel the writing with C-g and edit the buffer
   to remove or modify the problematic characters,
or specify any other coding system (and risk losing
   the problematic characters).

  utf-8 euc-jp shift_jis iso-2022-jp euc-jis-2004 iso-2022-jp-2004
  big5 euc-kr euc-tw gb2312 gb18030 gbk big5-hkscs hz-gb-2312 utf-7
  utf-16 utf-16be-with-signature utf-16le-with-signature utf-16be
  utf-16le japanese-shift-jis-2004 japanese-iso-7bit-1978-irv
  iso-2022-7bit utf-8-auto utf-8-with-signature eucjp-ms korean-cp949
  japanese-cp932 utf-7-imap utf-8-emacs

設定では utf-8 が優先されるようになっている

設定を確認してみると、~/.emacs.d/init.el の coding system 関連は以下のようになっています。

1
2
3
(set-language-environment "Japanese")
(prefer-coding-system 'utf-8-unix)
(set-default-coding-systems 'utf-8)

coding-system-priority-list を確認してみても、utf-8 が最優先になっています。

1
2
(coding-system-priority-list) C-j
(utf-8 japanese-iso-8bit iso-2022-jp japanese-shift-jis iso-2022-jp-2 iso-2022-7bit iso-latin-1 iso-2022-8bit-ss2 emacs-mule raw-text in-is13194-devanagari utf-8-auto ...)

読み込みの判定に問題有り

実験してみたところ、英字(アスキーコード) しかないファイルを読み込んだ際、Emacs が自動判定する coding system が undecided になってしまうのが原因だとわかりました。
ちなみに、判定された coding system は M-:buffer-file-coding-system を評価するとわかります。

解決策1 読み込みを強制的に utf-8 にする(非推奨)

読み込み時の coding system を強制的に utf-8 にすれば問題は解決です。
具体的には、以下を ~/.emacs.d/init.el に追加します。

1
(setq coding-system-for-read 'utf-8)

この方法、やってみるとちゃんと動作するのですが、読み込む全てのファイルを utf-8 にしてしまいます。 つまり、sjis のファイルなんかを読み込むと文字化けしてしまいます。

さらに、以下には coding-system-for-read はグローバルに設定すべきではない変数だと書いてあります。 GNU Emacs Lisp Reference Manual: Specifying Coding Systems

というわけで、他の方法が必要です。

解決策2 coding system 判定後に入れ替える

buffer-file-coding-systemundecided だった場合のみ coding system を変更するようにしてみました。
coding-system-for-read を一時的に変更してバッファを読み込み直すという方法です。
以下を ~/.emacs.d/init.el に追加します。

1
2
3
4
(add-hook 'find-file-hook '(lambda ()
                             (cond ((string-match "undecided-?.*" (format "%s" buffer-file-coding-system))
                                    (let ((coding-system-for-read 'utf-8))
                                      (revert-buffer t t))))))

いまのところ、この方法でうまく動いています。

0 件のコメント: