いまさら、IOのエンコーディングの便利さに気づいた

$stdout の外部エンコーディングを指定した

YamlUTF-8しかサポートしてないことに気付かされ、呆然としていたのは昨日のこと。
だって、Windowsだと、ソースを Windows-31Jで書いとかないと、特にテストの時にとてもとても不便だもん。
ちなみに、わたしは specの descriptionとか、全部日本語で書いてます。ソースにもばんばん日本語でコメントしちゃうどころか、データもソースに直書きしたりとか、フリーダムな感じで。
んで、今朝がた、IOって内部エンコーディングと外部エンコーディングの自動変換してくれるんじゃなかったけと思い出し。要はWindowsコマンドプロンプトWindows-31Jで出力してくれたらいいわけで、これってまさに、external_encoding を指定する局面じゃないでしょうか、と。
気が抜けるほど、あっさりいけました。

# -*- coding: UTF-8 -*-
$stdout.set_encoding('Windows-31J')
#(普通にコードを書く)

こやって書いとくと、puts したら文字化けせずにWindowsコマンドラインに表示されます。p だとダメですが。
こんなに便利なものだったのかー。もっと早く気づいておくべきでした。

rspec でちょと小細工した

ホクホクと、Brounieのソースを全部↑で直していったのですが。
テストが、failするコードを書いたら、テスト結果(「...*..F」とか出るやつ)は期待通りなのになんか出力の途中で Encoding::CompatibilityError が出てるるる。
UTF-8Windows-31J を繋げようして、例外が出てるので、明らかにいまの変更が悪い。。。
formatter なら、なんとかなるかなと思って、ソースを見に行って(こういうとこが、スクリプト言語って気軽で良いです)、エラーが出てるコードを片っ端から encode して実験。
結果として、〜location の類が Windows-31J で帰ってくるのがいけないぽい。パスに 2byte文字を使ってるからかー。
一般的に対処するなら、出力する IOの内部エンコーディングをとってきてとかするとこですが、めんどーだし自分しか使わない環境なので、自分ルールに書き換え。<後の自分が嵌りそうなやり方
base_text_formatter.rb の中で、RSpec::Core::Formatters::BaseTextFormatter の中のメソッド 2ヶ所に、encode('UTF-8') を追加してます。

def dump_commands_to_rerun_failed_examples
  # (略)
  failed_examples.each do |example|
  output.puts(red("rspec #{RSpec::Core::Metadata::relative_path(example.location).encode('UTF-8')}") + " " + cyan("# #{example.full_description}"))
end
def dump_shared_failure_info(group)
  output.puts "#{long_padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
   "#{backtrace_line(group.metadata[:example_group][:location]).encode('UTF-8')}"
end

コマンドプロンプトに、メッセージもデータもきれいに表示されるようになりました。
まんぞく♪
って、テストが期待通り failするとこに到達しただけなのだけど

(2012/11/06 追記) だめじゃん

むむむ、データが相変わらず文字化けしてることを発見。