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.04";
4              
5 2     2   78641 use v5.14;
  2         16  
6 2     2   10 use warnings;
  2         4  
  2         48  
7              
8 2     2   637 use utf8;
  2         15  
  2         11  
9 2     2   1199 use Encode;
  2         19520  
  2         151  
10 2     2   1094 use charnames ':full';
  2         61592  
  2         12  
11 2     2   1044 use Data::Dumper;
  2         5314  
  2         163  
12             {
13 2     2   17 no warnings 'redefine';
  2         4  
  2         226  
14 0     0   0 *Data::Dumper::qquote = sub { qq["${\(shift)}"] };
  0         0  
15             $Data::Dumper::Useperl = 1;
16             }
17 2     2   617 use open IO => 'utf8', ':std';
  2         1213  
  2         15  
18 2     2   1372 use Pod::Usage;
  2         74745  
  2         268  
19              
20 2     2   1201 use Getopt::EX::Hashed; {
  2         14042  
  2         17  
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   969 } no Getopt::EX::Hashed;
  2         5  
  2         10  
55              
56 2     2   1007 use App::ansiecho::Util;
  2         6  
  2         81  
57 2     2   852 use Getopt::EX v1.24.1;
  2         5103  
  2         76  
58 2     2   975 use Text::ANSI::Printf 2.01 qw(ansi_sprintf);
  2         72685  
  2         133  
59              
60 2     2   16 use List::Util qw(sum);
  2         5  
  2         338  
61              
62             sub run {
63 75     75 0 235384 my $app = shift;
64 75         247 $app->options(@_);
65 75         208 print join($app->separate, $app->retrieve), $app->terminate;
66             }
67              
68             sub options {
69 75     75 0 119 my $app = shift;
70 75         239 my @argv = decode_argv @_;
71 2     2   925 use Getopt::EX::Long qw(GetOptionsFromArray Configure ExConfigure);
  2         70613  
  2         300  
72 75         2488 ExConfigure BASECLASS => [ __PACKAGE__, "Getopt::EX" ];
73 75         1701 Configure qw(bundling no_getopt_compat pass_through);
74 75 50       4101 $app->getopt(\@argv) || pod2usage();
75 75         135283 $app->params(\@argv);
76 75         679 $app;
77             }
78              
79 2     2   21 use Term::ANSIColor::Concise qw(ansi_color ansi_code);
  2         4  
  2         2455  
80              
81             sub retrieve {
82 168     168 0 580 my $app = shift;
83 168         252 my $count = shift;
84 168         344 my $in = $app->params;
85 168         896 my @out;
86             my @pending;
87 168         0 my(@style, @effect);
88              
89             my $append = sub {
90 228     228   642 push @out, join '', splice(@pending), @_;
91 168         622 };
92              
93 168         412 while (@$in) {
94 289         486 my $arg = shift @$in;
95              
96             # -S
97 289 100       708 if ($arg =~ /^-S$/) {
98 4         34 unshift @style, [ \&ansi_code ];
99 4         11 next;
100             }
101             # -c, -C
102 285 100       662 if ($arg =~ /^-([cC])(.+)?$/) {
103 22 100       79 my $target = $1 eq 'c' ? \@effect : \@style;
104 22 100       95 my($color) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
105 21         92 unshift @$target, [ \&ansi_color, $color ];
106 21         54 next;
107             }
108             # -F
109 263 100       506 if ($arg =~ /^-(F)(.+)?$/) {
110 9 100       67 my($format) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
111 9         33 unshift @style, [ \&ansi_sprintf, $format ];
112 9         23 next;
113             }
114             # -E
115 254 100       453 if ($arg =~ /^-E$/) {
116 5         13 @style = ();
117 5         18 next;
118             }
119              
120             #
121             # -s, -i, -a : ANSI sequence
122             #
123 249 100       651 if ($arg =~ /^-([sia])(.+)?$/) {
    100          
124 18         43 my $opt = $1;
125 18   33     75 my $text = $2 // shift(@$in) // die "Not enough argument.\n";
      50        
126 18         53 my $code = ansi_code($text);
127 18 50       1713 if ($opt eq 's') {
128 0         0 $arg = $code;
129             } else {
130 18 100 100     70 if (@out == 0 or $opt eq 'i') {
131 12         24 push @pending, $code;
132             } else {
133 6         18 $out[-1] .= $code;
134             }
135 18         51 next;
136             }
137             }
138             #
139             # -f : format
140             #
141             elsif ($arg =~ /^-f(.+)?$/) {
142 38 50       163 my($format) = defined $1 ? safe_backslash($1) : $app->retrieve(1);
143             my $n = sum map {
144 37   100     301 { '%' => 0, '*' => 2, '*.*' => 3 }->{$_} // 1
  45         364  
145             } $format =~ /(?| %(%) | %[-+ #0]*+(\*(?:\.\*)?|.) )/xg;
146 37         100 $arg = ansi_sprintf($format, $app->retrieve($n));
147             }
148             #
149             # normal string argument
150             #
151             else {
152 193 100       490 if ($app->escape) {
153 192         1217 $arg = safe_backslash($arg);
154             }
155             }
156              
157             #
158             # apply @effect and @style
159             #
160 228         27813 for (splice(@effect), @style) {
161 70         3262 my($func, @opts) = @$_;
162 70         182 $arg = $func->(@opts, $arg);
163             }
164              
165 228         9104 $append->($arg);
166              
167 228 100       567 if ($count) {
168 106         183 my $out = @out + !!@pending;
169 106 50       225 die "Unexpected behavior.\n" if $out > $count;
170 106 100       232 last if $out == $count;
171             }
172             }
173 164 50       310 @pending and $append->();
174 164 100 100     533 die "Not enough argument.\n" if $count and @out < $count;
175 160         893 return @out;
176             }
177              
178             1;
179              
180             __END__