filenameプラグマを作ってみたよ。
filenameプラグマを作ってみたよ。
とりあえず作ってみた。たぶん動くんじゃないかな?
これを使って何をしたいかはまた後で。
名前
filename - utf8文字列なファイル名を変換したり、読み出したファイル名をutf8文字列に変換する方法を指定する
概要
use filename 'cp932'; open my $fh, '<', $filename;
use filenname 'cp932', qw/:globally/; # modify CORE::GLOBAL my $fh = IO::File->new( $filename, 'r' );
use filename \&_convert_cp932; open my $fh, '<', $filename; use Encode; my $enc = Encode::find_encoding('cp932'); sub _convert_cp932 { my $filename = shift; if (utf8::is_utf8($filename)) { $enc->encode($filename); } else { $enc->decode($filename); } }
注意
ファイルハンドル周りは挙動がよく分からないので、これで正しいのか自信がないです。
1引数のopen()には対応していません(すべき?)。
sysopen()にも対応していません(すべき?)。
予定
どれを使うか引数で指定できるようにしたほうがいい気がする。
Exporterを使うべきか悩みどころ。
希望
encodingプラグマと一緒に配布するとうれしいんじゃないかな?
ソースコード
package filename; our $VERSION = '0.01'; use strict; use Encode qw/is_utf8 find_encoding/; use Symbol qw/qualify_to_ref gensym/; sub import { my $pkg = shift; my $encoding = shift; my %opt = map +(lc $_ => 1), @_; my $convert; if (ref $encoding eq 'CODE') { $convert = $encoding; } else { my $enc = find_encoding($encoding); $convert = sub { my $filename = shift; if (is_utf8($filename)) { $enc->encode($filename); } else { $enc->decode($filename); } }; } my $where = $opt{':globally'}? 'CORE::GLOBAL': caller(0); no strict 'refs'; no warnings 'redefine'; my $open = eval {$where->can('open')}; *{"$where\::open"} = sub (*;$@) { my $fh; if (defined $_[0]) { $fh = qualify_to_ref(shift, caller); } else { $_[0] = gensym; $fh = shift; } if (@_ == 0) { $open? $open-> ($fh): CORE::open($fh); } elsif (@_ == 1) { my $expr = is_utf8($_[0])? $convert->($_[0]): $_[0]; $open? $open-> ($fh, $expr): CORE::open($fh, $expr); } elsif (@_ >= 2) { my $mode = shift; my $expr = is_utf8($_[0])? $convert->(shift): shift; $open? $open-> ($fh, $mode, $expr, @_): CORE::open($fh, $mode, $expr, @_); } }; my $opendir = eval {$where->can('opendir')}; *{"$where\::opendir"} = sub (*$) { my $dh; if (defined $_[0]) { $dh = qualify_to_ref(shift, caller); } else { $_[0] = gensym; $dh = shift; } my $expr = is_utf8($_[0])? $convert->($_[0]): $_[0]; $opendir? $opendir->($dh, $expr): CORE::opendir($dh, $expr); }; my $readdir = eval {$where->can('readdir')}; *{"$where\::readdir"} = sub (*) { my $dh = shift; unless (ref $dh) { $dh = qualify_to_ref($dh, caller); } my @res = $readdir? $readdir->($dh): CORE::readdir($dh); map +$convert->($_), @res; }; my $glob = eval {$where->can('glob')}; *{"$where\::glob"} = sub { my $pat = shift || $_; is_utf8($pat) and $pat = $convert->($pat); if (wantarray) { my @res = $glob? $glob->($pat): CORE::glob($pat); map +$convert->($_), @res; } else { my $res = $glob? $glob->($pat): CORE::glob($pat); $convert->( $res ); } }; } 1;