File Coverage

blib/lib/App/ansiecho.pm
Criterion Covered Total %
statement 110 113 97.3
branch 33 38 86.8
condition 10 13 76.9
subroutine 21 22 95.4
pod 0 3 0.0
total 174 189 92.0


line stmt bran cond sub pod time code
1             package App::ansiecho;
2              
3             our $VERSION = "1.03";
4              
5 2     2   83305 use v5.14;
  2         20  
6 2     2   11 use warnings;
  2         2  
  2         66  
7              
8 2     2   708 use utf8;
  2         31  
  2         16  
9 2     2   1266 use Encode;
  2         20655  
  2         152  
10 2     2   1254 use charnames ':full';
  2         65362  
  2         23  
11 2     2   1115 use Data::Dumper;
  2         5547  
  2         161  
12             {
13 2     2   15 no warnings 'redefine';
  2         4  
  2         238  
14 0     0   0 *Data::Dumper::qquote = sub { qq["${\(shift)}"] };
  0         0  
15             $Data::Dumper::Useperl = 1;
16             }
17 2     2   610 use open IO => 'utf8', ':std';
  2         1253  
  2         15  
18 2     2   1436 use Pod::Usage;
  2         78236  
  2         315  
19              
20 2     2   1169 use Getopt::EX::Hashed; {
  2         14650  
  2         12  
21             Getopt::EX::Hashed->configure(DEFAULT => [ is => 'rw' ]);
22             has debug => " " ;
23             has n => " " , action => sub { $_->terminate = '' };
24             has join => " j " , action => sub { $_->separate = '' };
25             has escape => " e ! " , default => 1;
26             has rgb24 => " ! " ;
27             has separate => " =s " , default => " ";
28             has help => " h " ;
29             has version => " v " ;
30              
31             has '+separate' => sub {
32             my($name, $arg) = map "$_", @_;
33             $_->$name = safe_backslash($arg);
34             };
35              
36             has '+rgb24' => sub {
37             $Term::ANSIColor::Concise::RGB24 = !!$_[1];
38             };
39              
40             has '+help' => sub {
41             pod2usage
42             -verbose => 99,
43             -sections => [ qw(SYNOPSIS VERSION) ];
44             };
45              
46             has '+version' => sub {
47             say "Version: $VERSION";
48             exit;
49             };
50              
51             has terminate => default => "\n";
52             has params => default => [];
53              
54 2     2   1048 } no Getopt::EX::Hashed;
  2         9  
  2         9  
55              
56 2     2   1056 use App::ansiecho::Util;
  2         6  
  2         80  
57 2     2   930 use Getopt::EX v1.24.1;
  2         5222  
  2         77  
58 2     2   965 use Text::ANSI::Printf 2.01 qw(ansi_sprintf);
  2         74117  
  2         144  
59              
60 2     2   18 use List::Util qw(sum);
  2         4  
  2         314  
61              
62             sub run {
63 72     72 0 226303 my $app = shift;
64 72         232 $app->options(@_);
65 72         183 print join($app->separate, $app->retrieve), $app->terminate;
66             }
67              
68             sub options {
69 72     72 0 111 my $app = shift;
70 72         242 my @argv = decode_argv @_;
71 2     2   982 use Getopt::EX::Long qw(GetOptionsFromArray Configure ExConfigure);
  2         74080  
  2         352  
72 72         2307 ExConfigure BASECLASS => [ __PACKAGE__, "Getopt::EX" ];
73 72         1606 Configure qw(bundling no_getopt_compat pass_through);
74 72 50       3995 $app->getopt(\@argv) || pod2usage();
75 72         129700 $app->params(\@argv);
76 72         609 $app;
77             }
78              
79 2     2   27 use Term::ANSIColor::Concise qw(ansi_color ansi_code);
  2         5  
  2         2581  
80              
81             sub retrieve {
82 165     165 0 545 my $app = shift;
83 165         242 my $count = shift;
84 165         322 my $in = $app->params;
85 165         856 my @out;
86             my @pending;
87 165         0 my(@style, @effect);
88              
89             my $append = sub {
90 225     225   614 push @out, join '', splice(@pending), @_;
91 165         576 };
92              
93 165         383 while (@$in) {
94 286         452 my $arg = shift @$in;
95              
96             # -S
97 286 100       637 if ($arg =~ /^-S$/) {
98 4         11 unshift @style, [ \&ansi_code ];
99 4         13 next;
100             }
101             # -c, -C
102 282 100       613 if ($arg =~ /^-([cC])(.+)?$/) {
103 22 100       90 my $target = $1 eq 'c' ? \@effect : \@style;
104 22 100       113 my($color) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
105 21         90 unshift @$target, [ \&ansi_color, $color ];
106 21         54 next;
107             }
108             # -F
109 260 100       505 if ($arg =~ /^-(F)(.+)?$/) {
110 9 100       37 my($format) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
111 9         32 unshift @style, [ \&ansi_sprintf, $format ];
112 9         23 next;
113             }
114             # -E
115 251 100       468 if ($arg =~ /^-E$/) {
116 5         14 @style = ();
117 5         16 next;
118             }
119              
120             #
121             # -s, -i, -a : ANSI sequence
122             #
123 246 100       637 if ($arg =~ /^-([sia])(.+)?$/) {
    100          
124 18         43 my $opt = $1;
125 18   33     76 my $text = $2 // shift(@$in) // die "Not enough argument.\n";
      50        
126 18         50 my $code = ansi_code($text);
127 18 50       1700 if ($opt eq 's') {
128 0         0 $arg = $code;
129             } else {
130 18 100 100     78 if (@out == 0 or $opt eq 'i') {
131 12         21 push @pending, $code;
132             } else {
133 6         23 $out[-1] .= $code;
134             }
135 18         52 next;
136             }
137             }
138             #
139             # -f : format
140             #
141             elsif ($arg =~ /^-f(.+)?$/) {
142 38 50       148 my($format) = defined $1 ? safe_backslash($1) : $app->retrieve(1);
143             my $n = sum map {
144 37   100     288 { '%' => 0, '*' => 2, '*.*' => 3 }->{$_} // 1
  45         368  
145             } $format =~ /(?| %(%) | %[-+ #0]*+(\*(?:\.\*)?|.) )/xg;
146 37         105 $arg = ansi_sprintf($format, $app->retrieve($n));
147             }
148             #
149             # normal string argument
150             #
151             else {
152 190 100       463 if ($app->escape) {
153 189         1118 $arg = safe_backslash($arg);
154             }
155             }
156              
157             #
158             # apply @effect and @style
159             #
160 225         28469 for (splice(@effect), @style) {
161 70         3193 my($func, @opts) = @$_;
162 70         230 $arg = $func->(@opts, $arg);
163             }
164              
165 225         9344 $append->($arg);
166              
167 225 100       557 if ($count) {
168 106         177 my $out = @out + !!@pending;
169 106 50       213 die "Unexpected behavior.\n" if $out > $count;
170 106 100       267 last if $out == $count;
171             }
172             }
173 161 50       319 @pending and $append->();
174 161 100 100     513 die "Not enough argument.\n" if $count and @out < $count;
175 157         834 return @out;
176             }
177              
178             1;
179              
180             __END__