@kyanny's blog

My thoughts, my life. Views/opinions are my own.

Emacs の文字コード自動判別を学ぶ(セーブ時に勝手に文字コードを変更させない)

Selected encoding XXXX disagrees with XXXX specified by file contents. というエラー - 刺身☆ブーメランのはてなダイアリー コメントで教えていただいた、 auto-coding-functions という変数を describe-variable でみてみると、自分の環境では(.emacs とかを読ませたあとでは)以下のようになった。

M-x describe-variable auto-coding-functions
auto-coding-functions is a variable defined in `mule.el'.
Its value is 
(sgml-xml-auto-coding-function sgml-html-meta-auto-coding-function)

Emacs を -q オプションつきで、 .emacs を読ませないで起動した場合は、こうなった。

auto-coding-functions is a variable defined in `mule.el'.
Its value is 
(sgml-xml-auto-coding-function sgml-html-meta-auto-coding-function)

あれ変わってないな・・・。予想だと -q つきのときはここが nil で、 ~/.emacs.d 以下にいろいろ入れていた elisp がロード時にこの変数を書き換えてるせいで文字コードの自動判別に失敗しているんだと思ったんだけど。そうではないみたいだ。

この変数を nil にしてみては、という指摘だったのでそうしてみたがうまくいかなかった・・・と思ってコメントしたあとでもう一回手順を整理してやってみたら、うまくいった。

  • livedoor Blog - 新着モブログ をファイルとして保存する (moblog.xml)
  • iconv -f utf-8 -t euc-jp moblog.xml > moblog_euc.xml で、 XML 宣言で encoding="UTF-8" としてあるが実際には euc-jp で保存されているファイルを作る
  • auto-coding-functions を起動時の値のままにしておいてからこれらのファイルを開くと、 moblog.xml も moblog_euc.xml も utf-8 で開いてしまう
  • (setq auto-coding-functions nil) としてから開き直すと、 moblog.xml は utf-8 で、 moblog_euc.xml は euc-jp で開いてくれる(期待した動作)
  • それぞれバッファを変更してセーブしなおすと、 moblog.xml は utf-8 で保存され、 moblog_euc.xml は euc-jp で保存される

一番下のセーブ時の動作がキモで、 auto-coding-functions が nil でない(というか sgml-xml-auto-coding-functions とかがセットされている)場合だと、たぶん XML 宣言の encoding="UTF-8" を見て勝手に utf-8 で保存しようとしてしまう。これは意図した動作ではないし、文字化けする(意図的に encoding="UTF-8" と宣言された euc-jp エンコーディングで書かれたファイルを作ってるほうにそもそもの問題があるわけだが)。

で、 auto-coding-functions が nil だと、そこの判別はせずにもともとのファイル、なのかバッファなのか、ともかくそれの文字コードでもって保存してくれる。これは期待した動作だ。そしてちゃんとファイルを開いたときには文字コードの自動判別そのものはしてくれている。このへんがなぜうまくいくのかはまだわからない。けど、いい感じになった。