書き込み対象の日記
Permanent Link: http://www.misho-web.com/diary/200903.html#Diary28
Unix Shellでの出力(色およびencode)を,DOS Shell用に変換するwrapperを作った。
よく知られているように,Unix系のshell consoleと,WindowsのDOS shell consoleは全然違う。特にUnix shell系向けに作られたprogramをWindowsで実行すると,
- 文字code
- 制御文字による色の変更
の2点で問題が現れる。
僕は仕事で Ruby / RSpec を使って開発しているのだけれど,RSpecの鮮やかな出力がWindowsだとなんか文字化けしたような感じに見えてしまう。もちろん色については先駆者が居て,確かにこのようにすればDOSでもちゃんと色付きで表示される。
しかし,これでもやはり問題がある。僕の環境では,RSpecの出力がUTF-8なのに対して,DOS console はShift_Jisしか認識してくれない。これではあの有名なfaultierさんを見習って頑張って日本語で書いたRSpecの意味が全然分からないことになる!!
もちろんこれについても色々な解決案があるようなのだけれど,でも色を付けた上で文字化けを解決する手段が見つからなかったのだ。
なんかもう色々めんどくさかったのでしばらくは文字化けしたままで使っていたが,いい加減なんとかしようという気になったので,ちょっとWrapperを書いてみた。
package ShellToDos;
use Win32::Console;
use Encode;
# black, red, green, yellow,
# blue, magenda, cyan, white
my $HASH = { 30=>0, 31=> 4, 32=> 2, 33=> 6,
34=>1, 35=> 5, 36=> 3, 37=> 7, };
my $VIVID = { 30=>0, 31=>12, 32=>10, 33=>14,
34=>9, 35=>13, 36=>11, 37=>15, };
sub new{
my $class = shift;
my $vivid = shift;
my $in = shift || 'utf-8';
my $out = shift || 'shiftjis';
my $c = new Win32::Console(STD_OUTPUT_HANDLE);
my $h = $vivid ? $VIVID : $HASH; # Color Hash
$h->{0} = ($c -> Attr); # Default Value
$| = 1;
bless { console => $c, hash => $h,
in => $in, out => $out }, $class;
}
sub output{
my($self, $str) = @_;
Encode::from_to($str, $self->{in}, $self->{out});
my @output = split(//, $str);
print shift(@output);
foreach(@output){
$_ =~ s/\[(\d+)m//;
($self->{console}) -> Attr($self->{hash}->{$1});
print $_;
}
}
sub DESTROY{
my $self = shift;
($self -> {console}) -> Attr($self->{hash}->{0});
$| = 0;
}
1;
Constructorの引数は,
- $vivid : 表示を鮮やかにするかどうか。DEFAULT : 0 (false)
- $in : 入力時のencoding。DEFAULT : utf-8
- $out : 出力時のencoding。通常は指定しなくて良い。DEFAULT : shiftjis
の3つ。まぁ何もしなくても死にはしない。
こいつをShellToDos.pmみたいな感じで保存して,
#!/usr/bin/perl
use ShellToDos;
my $wrapper = new ShellToDos(1);
$wrapper -> output("andy[31mRED\nRED[32mGR\nEEEEEN[0mandy\n");
とかすれば,何もかもうまくいく。ちなみにこのsampleで見えている“[32m”みたいなやつが,Unix shellのいわゆる色変更命令。WindowsでRSpecを実行した人はみな,この忌まわしき文字列がずらーっと画面上に並ぶあの絶望感を知っているはずだ。
ちなみに例では日本語は処理させていないけれども,ちゃんとconstructorにinput encodingを与えれば日本語も正しく処理できる。
RSpecとかautospecとかの結果も,wrapper.plとして
#!/usr/bin/perl
use ShellToDos;
my $cmd = $ARGV[0];
my $wrapper = new ShellToDos(1);
open(PIPE, "$cmd |") or die "Can't open pipe $cmd";
while(<PIPE>){
$wrapper -> output($_);
}
close(PIPE);
とかを書いて,DOS promptからperl wrapper.pl autospecみたいな感じで実行してやれば,日本語も化けないし色もきれいに表示される!!!!……のだけど,CTRL+Z による reset / halt がうまく動かないの><。どうしよう……。。。。
Comments
Commented by alice at 2009/03/30(Mon) 01:57:24
この日記をぱくってmixiに丸写ししてみよう
誰かコメントくれるかな??w
< Commentを書き込む >
[Trackback URL : http://www.misho-web.com/diary/Trackback/20090328]
