ルモーリン
ホーム 更新 Perl Sample ランドナー サービス 雑談 コースガイド 鉄ゲタ 自転車 Linux リンク 連絡先

dieのメッセージをエンコードするモジュール

2018-12-21

前回までのあらすじ

エンコードしない場合のトラブルとdieの代替処理を書くところまで。
エラー出力が出ない

モジュールのコード

こんなモジュールをデッチ上げました。 大抵のモジュールはパッケージ名を指定しますけれど、こいつはパッケージ名を書いてないので呼び出したパッケージ内にdieが定義されます。
use utf8;
use Encode::Locale;
use subs "die";

sub die {
	my @msg = @_;

	if (@_ && $msg[-1] =~ /\n$/) {
		@msg = map {Encode::encode console_out => $_} @msg;

		CORE::die @msg;
	} else {
		$msg[0] = "Died" if !@msg;

		my (undef, $filename, $line) = caller;
		$filename = Encode::decode locale_fs => $filename;
		$line = Encode::decode locale => $line;

		CORE::die Encode::encode console_out => "@msg at $filename line $line.\n";
	}
}

1;

使用例

こんなコードです。 スクリプトと同じディレクトリのモジュール/ファイルを指定できるようにFindBinを使います。
#!/usr/bin/env perl -w

use utf8;
use strict;
use warnings;

use v5.10;
use Encode::Locale;

use FindBin;
use lib $FindBin::Bin;

use MyDie;

use open IO => ":utf8";

binmode STDOUT, ":encoding(console_out)";
binmode STDIN, ":encoding(console_in)";

$| = 1;

my $target = Encode::decode locale_fs => "$FindBin::Bin/not_exist.txt";
open my $fh, "<", $target or die "${target}が開かないよ。$!";

exit;

実行結果

まあ、見た目は普通ですね。 この「普通」を叶えるために色々と工夫する手間が好きです。
C:\>perl ああああああ/sample_45.pl
C:/ああああああ/not_exist.txtが開かないよ。No such file or directory at ああああああ/sample_45.pl line 23.

テスト

初めてテストを書いてみました。 モジュールがあるディレクトリにディレクトリ「t」を作り、case1.tを書きました。
use utf8;
use strict;
use warnings;

use Test::More;
use Test::Exception;

use FindBin;
use lib "$FindBin::Bin/..";

use MyDie;

use open IO => ":utf8";

binmode STDOUT, ":encoding(console_out)";
binmode STDIN, ":encoding(console_in)";

$| = 1;

# 普通のメッセージでは、ファイル名と行位置そして"line"を表示
dies_ok {
	die "本日は晴天なり。";
} "line";

# 最後のメッセージの末尾に改行があると、メッセージだけ
dies_ok {
	die "本日は晴天なり。\n";
} Encode::encode console_out => "本日は晴天なり。";

# メッセージがなければ"Died"で代替
dies_ok {
	die;
} "Died";

done_testing;