北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

POE::Wheel::ReadLine で日本語を使うパッチ

POE::Wheel::ReadLine は便利なのですが日本語が使えません。なので、パッチを書きました。

使い方

利用は自己責任でお願いしますm(_ _)m。

ReadLine-1.003.patchをDLして、ReadLine.pmにあててください。でもって、POE/Wheel/ReadLine/JP.pmをインクルードパスが通ってるとこに置いて下さい*1

ソース側では、UTF-8でいい場合は、

use POE qw(Wheel::ReadLine::JP);

他の文字コードの時は、

use POE qw(Wheel::ReadLine);
use POE::Wheel::ReadLine::JP (charset => 'euc-jp');

等として下さい。

パッチの説明

内部でバイト列を保持していたのを、unicode文字列で保持するように変更しています。伴い、本体側で以下の変更をしました。

"use bytes" を消した

一番ハマったとこかも。こんなプラグマ知らなかったですよ・・・。

全半角の判断

Unicode::EastAsianWidth で文字の印字幅(全角か半角か)取得してます。(→こちらのエントリ参照)

length(_normalize($str)) != _display_width($str)

_normalizeはエスケープ文字とかを可視化する関数で、_display_widthは表示幅を計算する関数です。今までは_normalizeした結果はASCIIだったのでlengthを取れば_display_widthになったのですが、Unicode文字列だと事情が変わります。

例えば、「あ」にlengthをかけると、utf8化されてれば1文字、されてなければ3byteです。でも、_display_widthは表示幅なので2です。

_normalize関数を修正

ord取った時に0xFFを超える文字は消しちゃう仕様だったので、変更。utf8文字だと、0xFF以上返すんですよねー。

フックの作成

日本語化は別モジュールでやりたかったので、本体にはフックだけ入れました。

  • $POE::Wheel::ReadLine::stdin, stdout
    • 標準入出力。PerlIO噛ませなければならんので。
  • POE::Wheel::ReadLine::_display_bytes()
    • 表示幅の取得関数。本体では単なるlengthです。
  • POE::Wheel::ReadLine::_read_char()
    • キーボードから1byteではなく1文字読み込む関数。本体では単なるReadKey(-1)です。