File Coverage

blib/lib/App/PPE.pm
Criterion Covered Total %
statement 51 73 69.8
branch 9 20 45.0
condition 2 4 50.0
subroutine 14 18 77.7
pod 0 6 0.0
total 76 121 62.8


line stmt bran cond sub pod time code
1             package App::PPE;
2 2     2   53586 use 5.008001;
  2         13  
3 2     2   8 use strict;
  2         2  
  2         30  
4 2     2   7 use warnings;
  2         2  
  2         67  
5              
6             our $VERSION = "0.04";
7              
8 2     2   757 use Parse::ErrorString::Perl;
  2         47772  
  2         54  
9 2     2   925 use Term::ANSIColor qw//;
  2         12769  
  2         1488  
10              
11             # https://perldoc.perl.org/perldiag.html#DESCRIPTION
12             our $TAG_MAP = {
13             W => 'WARN',
14             D => 'WARN',
15             S => 'WARN',
16             F => 'CRITICAL',
17             P => 'CRITICAL',
18             X => 'ERROR',
19             A => 'ERROR',
20              
21             undef => 'UNKNOWN',
22             };
23              
24             our $COLOR = {
25             'warn' => {
26             text => 'black',
27             background => 'yellow',
28             },
29             'critical' => {
30             text => 'black',
31             background => 'red'
32             },
33             'error' => {
34             text => 'red',
35             background => 'black'
36             },
37             'unknown' => {
38             text => 'white',
39             background => 'red'
40             }
41             };
42              
43             our $FORMAT = sub {
44             my ($tag, $type, $message, $file, $line) = @_;
45             return "$file:$line: [$tag] ($type) $message";
46             };
47              
48              
49              
50             sub new_with_options {
51 0     0 0 0 my ($class, @argv) = @_;
52              
53 0         0 my ($opt) = $class->parse_options(@argv);
54 0         0 $class->new($opt);
55             }
56              
57             sub parse_options {
58 0     0 0 0 my ($class, @argv) = @_;
59              
60 0 0       0 if (grep /^--?h(?:elp)?$/, @argv) {
61 0         0 _print_usage();
62             }
63              
64 0         0 my $opt = {};
65 0         0 my @rest;
66 0         0 for my $v (@argv) {
67 0 0       0 if ($v eq '--no-color') {
68 0         0 $opt->{color} = undef;
69 0         0 next;
70             }
71 0         0 push @rest, $v;
72             }
73 0         0 ($opt, \@rest)
74             }
75              
76             sub new {
77 1     1 0 68 my $class = shift;
78              
79 1 50       5 my $opt = @_ == 1 ? $_[0] : {@_};
80 1 50       3 unless (exists $opt->{parser}) {
81 1         8 $opt->{parser} = Parse::ErrorString::Perl->new()
82             }
83              
84 1 50       1153573 unless (exists $opt->{color}) {
85 0         0 $opt->{color} = 1;
86             }
87              
88 1         7 bless $opt, $class;
89             }
90              
91             sub run {
92 0     0 0 0 my $self = shift;
93 0         0 print $self->prettify_perl_error($_) . "\n" while
94             }
95              
96             sub prettify_perl_error {
97 2     2 0 9 my ($self, $perl_error) = @_;
98              
99 2         10 my ($error_item) = $self->{parser}->parse_string($perl_error);
100 2 100       14592 return $perl_error unless $error_item;
101 1         5 $self->prettify_error_item($error_item);
102             }
103              
104             sub prettify_error_item {
105 1     1 0 3 my ($self, $error_item) = @_;
106              
107 1         4 my $tag = $self->_prettify_tag($error_item);
108 1         3 my $type = $self->_prettify_type($error_item);
109 1         3 my $message = $self->_prettify_message($error_item);
110 1         3 my $file = $self->_prettify_file($error_item);
111              
112 1         6 $FORMAT->($tag, $type, $message, $file, $error_item->line);
113             }
114              
115             sub _tag {
116 1     1   1 my $error_item = shift;
117 1   50     94 my $type = $error_item->type // 'undef';
118 1         4 return $TAG_MAP->{$type};
119             }
120              
121             sub _prettify_color {
122 1     1   3 my ($self, $error_item) = @_;
123              
124 1 50       4 return {} unless $self->{color};
125              
126 0         0 my $tag = _tag($error_item);
127 0         0 my $color = $COLOR->{lc($tag)};
128              
129 0         0 return $color;
130             }
131              
132             sub _prettify_tag {
133 1     1   3 my ($self, $error_item) = @_;
134              
135 1         5 my $tag = _tag($error_item);
136 1         7 my $color = $self->_prettify_color($error_item);
137 1 50       3 $tag = Term::ANSIColor::color($color->{text}) . $tag . Term::ANSIColor::color("reset") if $color->{text};
138 1 50       4 $tag = Term::ANSIColor::color("on_".$color->{background}) . $tag . Term::ANSIColor::color("reset") if $color->{background};
139              
140 1         3 return $tag;
141             }
142              
143             sub _prettify_type {
144 1     1   3 my ($self, $error_item) = @_;
145 1   50     4 return $error_item->type // 'undef';
146             }
147              
148             sub _prettify_message {
149 1     1   2 my ($self, $error_item) = @_;
150              
151 1         2 my $message = $error_item->message;
152 1 50       4 if (my $near = $error_item->near) {
153 1         4 $near =~ s/:$//;
154 1         3 $message .= ", near " . $near;
155             }
156              
157 1         2 return $message;
158             }
159              
160             sub _prettify_file {
161 1     1   2 my ($self, $error_item) = @_;
162 1         3 return $error_item->file;
163             }
164              
165              
166             sub _print_usage {
167 0     0     print <<'EOS';
168             $ echo 'syntax error at /home/kfly8/foo.pl line 52, near "$foo:"' | ppe
169             foo.pl:52: [CRITICAL] syntax error: near $foo
170             EOS
171              
172 0           exit;
173             }
174              
175             1;
176             __END__