Text::ASCIITableを 2文字幅の文字に対応させる
Text::ASCIITableがmulti-width charactersに対応していないようですよ!腕に覚えのあるPerl Mongerにおかれましてはパッチを書いてみてはいかがでしょうか!!
このようにText::ASCIITableはデフォルトでは半角文字だけで日本語等の
全角幅の文字を含めるとテーブルにずれが生じてしまいます。
#!perl use strict; use warnings; use utf8; use Text::ASCIITable; binmode STDOUT, ":utf8"; my $japanese_table = Text::ASCIITable->new({headingText => '価格表',}); $japanese_table->setCols('名前', '値段', '在庫'); $japanese_table->addRow('りんご(apple)', '80円', '1000個'); $japanese_table->addRow('バナナ(banana)', '120円', '8500本'); $japanese_table->addRow('スイカ(watermelon)', '500円', '35玉'); print $japanese_table;
上記のプログラムを実行すると以下のようになり、ずれます。
コピペだとずれるので, 画像にしてます。
(端末エミュレータは MacOSXの iTerm2 Monaco + Osakaフォント)
修正
Text::ASCIITableは文字長を取得するために, length関数を使っています。
ASCIIなので、文字長 = 文字幅になるのですが、日本語のような言語では
そうならないので、length関数を上書きすることで対応を行いました。
ビルトイン関数を書き換えるのはどうかとも思うのですが、とりあえず
一番簡単な対応方法だと思います。コードは以下のとおりです。
文字幅の取得はこちらを参照しました.
#!perl use strict; use warnings; use utf8; use Unicode::EastAsianWidth; BEGIN { no warnings 'redefine'; *CORE::GLOBAL::length = sub { my $str = shift; my $width = 0; while ($str =~ m/(?:(\p{InFullwidth}+)|(\p{InHalfwidth}+))/go) { $width += ($1 ? length($1) * 2 : length($2)); } return $width; }; require Text::ASCIITable; }; binmode STDOUT, ":utf8"; my $japanese_table = Text::ASCIITable->new({ headingText => '価格表', }); $japanese_table->setCols('名前', '値段', '在庫'); $japanese_table->addRow('りんご(apple)', '80円', '1000個'); $japanese_table->addRow('バナナ(banana)', '120円', '8500本'); $japanese_table->addRow('スイカ(watermelon)', '500円', '35玉'); print $japanese_table;
結果は以下のようになります。(環境は上記と同じです)
考察
Text::ASCIITableを 2文字幅の文字(東アジア限定)に対応させる方法を
示しました。修正にあたり思ったのですが、Text::ASCIITableはドキュメントに
'using ASCII Charsets'と書いているから, Text::ASCIITableモジュールで対応
させるのは正しくないかもしれません.
世界の文字で全角・半角が分かれてるのってアジアだけなんですかね ?
UNICODEでEAST_ASIAN_WIDTHっていうトピックが
わざわざあるのは、東アジア限定だからなのかな?それだったら、
Text::ASCIIWidthの length部分を上記の関数に書き換えるだけで対応可能です。
ただ今後文字が増えて、アジア地域以外にも全角文字導入ということになると、
別モジュール(Text::ASCIITable::EastAsian)みたいにした方がいいかもしれません。