ライブラリのM17Nについての自分向けメモ

自分向けに要点だけメモっとく。
1.9対応かつM17Nでちゃんと動くように作る場合に
あとでこのメモを参照しよう。

  • 基本的に入力も出力もUnicode(UTF-8)を想定する。
  • Encoding#default_internal が設定されている場合はそのエンコーディングで返す
  • 入力については、String#encodingを見る
  • DummyEncodingは文字列として扱えない。
  • ユーザがString#force_encodingしないとならないようでは、M17N対応できたライブラリとは言えない。

ほとんどのライブラリは入出力はUTF-8だけを想定していていいんだけど、
ライブラリの性質上、どうしてもUTF-8以外のエンコーディングを入出力で取り扱わなければならない場合は、入力されたStringのString#encodingを確認したり、Encoding#defualt_internalを確認して、よきに計らうようにするといい。

Encoding#default_internal は、コマンドラインオプションの -Eや、-Uを使うか、マジックコメントに記述することで設定される。
異なるエンコーディングの入出力を想定せざるを得ないライブラリの場合は、ライブラリ自体にはマジックコメントでエンコーディング設定しない方がいいのかもしれない。
なぜなら、それをやってしまうとEncoding#default_internalやEncoding#default_externalを上書きしてしまうからだ。
*1

5/11 追記

気になったので マジックコメント をrequireされる側に書いてみた場合の挙動について確認しました。
マジックコメント に書いても、Encoding#defualt_external が上書きされるわけではなく。
マジックコメント の値は、まず __ENCODING__ に代入されるようです。
そして、 __ENCODING__ には感染性*2はないようです。*3
つまり、ライブラリ自体に magick comment を書いても問題はないわけですね。
むしろ、書くべきだったようです。*4

enc_euc.rb

#-*- encoding: euc-jp -*-
str_euc = 'ほげ'

require_euc.rb

#-*- encoding: utf-8 -*-

# -Eオプションや -Kオプションなしだと、 default_external は US-ASCII
p Encoding.defualt_external #=> #<Encoding:US-ASCII>

# スクリプトエンコーディング(__ENCODING__) は、 マジックコメントで指定したもの。
p __ENCODING__ #=> #<Encoding:UTF-8>

require 'enc_euc'

# require しても、Encoding.default_externalもスクリプトエンコーディングもちゃんと保持されるね。
p Encoding.defualt_external #=> #<Encoding:US-ASCII>
p __ENCODING__ #=> #<Encoding:UTF-8>

自分向けのまとめとしてはこんなところ。
……というか、ぜんぜんまとまってないじゃないか!

M17N恐るべし。
普及したらえらい便利なのだろうけれど、1.9初学者には最大の壁なのかも……

1.9対応したつもりの、手持ちのGemたちも内容確認したほうがいいかも。

*1:この点については、要検証

*2:微妙な表現だけど、自分としては判りやすい

*3:少なくとも、1.9.1-p0では。

*4:参考: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/33647