着色忏悔/鲤鱼消息

时间:2016-01-11 20:52:10

标签: perl

我编写了一个向终端输出大量消息的脚本。某些消息是提供信息的,其他消息是从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");
    }
}

输出如下(使用不同的行号):

enter image description here

问题是颜色过早重置,因此堆栈跟踪没有着色。如果省略color("reset")调用,堆栈跟踪也会着色,但是程序退出后终端提示符,并且终端中运行的所有后续命令的输出都是红色。

这有可能实现吗?我已经尝试了$SIG{__DIE__}处理程序和END块,但它没有用。

另见Coloring a perl die message

1 个答案:

答案 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.");