我编写了一个向终端输出大量消息的脚本。某些消息是提供信息的,其他消息是从Shell命令输出的,有些是错误消息。为了让用户轻松读取终端中的输出,我想用红色为错误消息着色。
除Carp::confess
生成的错误消息外,此方法正常。例如:
use strict;
use warnings;
use Carp;
use Term::ANSIColor;
my_func(1);
sub my_func {
my ( $val ) = @_;
if( $val != 0 ) {
confess color("bold red")
. "Unexpected value. Abort." . color("reset");
}
}
输出如下(使用不同的行号):
问题是颜色过早重置,因此堆栈跟踪没有着色。如果省略color("reset")
调用,堆栈跟踪也会着色,但是程序退出后终端提示符,并且终端中运行的所有后续命令的输出都是红色。
这有可能实现吗?我已经尝试了$SIG{__DIE__}
处理程序和END
块,但它没有用。
答案 0 :(得分:2)
似乎可以使用模具信号处理程序完成(达到令人满意的水平)。由于die信号处理程序捕获的内容远远多于confess
的调用(有关更多信息,请参阅Override die with END or CORE::GLOBAL::die),我们将检查给定的前导ANSI转义序列的die处理程序的输入参数。如果输入字符串包含color("red")
,我们将假设我们被confess
调用:
local $SIG{__DIE__} = sub {
my ( $msg) = @_;
my $col_red = color( "bold red" );
if ( $msg =~ /\Q$col_red\E/ ) {
$msg =~ s/\s+$//;
$msg .= (color("reset") . "\n");
}
die $msg;
};
然后,在我们编写的程序中
confess color("bold red") . "Unexpected value. Abort.";
因此省略了color("reset")
代码。
修改强>
可以获得对上述的改进。由于脚本已经控制了每个confess
调用,因此可以编写一个辅助子例程来进一步本地化信号处理程序:
sub error_exit {
my ( $msg ) = @_;
local $SIG{__DIE__} = sub {
my ( $msg) = @_;
my $col_red = color( "bold red" );
if ( $msg =~ /\Q$col_red\E/ ) {
$msg =~ s/\s+$//;
die $msg . color("reset") . "\n";
}
else {
die $msg;
}
};
confess color("bold red") . $msg;
}
然后,在脚本中,使用confess
调用替换每个error_exit
来电。例如,对于问题中的脚本:
error_exit("Unexpected value. Abort.");