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.02";
4              
5 2     2   66890 use v5.14;
  2         16  
6 2     2   9 use warnings;
  2         4  
  2         52  
7              
8 2     2   508 use utf8;
  2         16  
  2         10  
9 2     2   1754 use Encode;
  2         16909  
  2         121  
10 2     2   869 use charnames ':full';
  2         50213  
  2         13  
11 2     2   863 use Data::Dumper;
  2         4304  
  2         139  
12             {
13 2     2   15 no warnings 'redefine';
  2         3  
  2         195  
14 0     0   0 *Data::Dumper::qquote = sub { qq["${\(shift)}"] };
  0         0  
15             $Data::Dumper::Useperl = 1;
16             }
17 2     2   997 use open IO => 'utf8', ':std';
  2         958  
  2         12  
18 2     2   1153 use Pod::Usage;
  2         62938  
  2         241  
19              
20 2     2   933 use Getopt::EX::Hashed; {
  2         12486  
  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   799 } no Getopt::EX::Hashed;
  2         5  
  2         8  
55              
56 2     2   862 use App::ansiecho::Util;
  2         6  
  2         69  
57 2     2   784 use Getopt::EX v1.24.1;
  2         4271  
  2         63  
58 2     2   781 use Text::ANSI::Printf 2.01 qw(ansi_sprintf);
  2         62345  
  2         115  
59              
60 2     2   16 use List::Util qw(sum);
  2         4  
  2         247  
61              
62             sub run {
63 72     72 0 169747 my $app = shift;
64 72         181 $app->options(@_);
65 72         190 print join($app->separate, $app->retrieve), $app->terminate;
66             }
67              
68             sub options {
69 72     72 0 86 my $app = shift;
70 72         180 my @argv = decode_argv @_;
71 2     2   829 use Getopt::EX::Long qw(GetOptionsFromArray Configure ExConfigure);
  2         58758  
  2         252  
72 72         1887 ExConfigure BASECLASS => [ __PACKAGE__, "Getopt::EX" ];
73 72         1339 Configure qw(bundling no_getopt_compat pass_through);
74 72 50       3265 $app->getopt(\@argv) || pod2usage();
75 72         105982 $app->params(\@argv);
76 72         483 $app;
77             }
78              
79 2     2   15 use Term::ANSIColor::Concise qw(ansi_color ansi_code);
  2         4  
  2         1913  
80              
81             sub retrieve {
82 165     165 0 470 my $app = shift;
83 165         177 my $count = shift;
84 165         268 my $in = $app->params;
85 165         689 my @out;
86             my @pending;
87 165         0 my(@style, @effect);
88              
89             my $append = sub {
90 225     225   490 push @out, join '', splice(@pending), @_;
91 165         489 };
92              
93 165         332 while (@$in) {
94 286         406 my $arg = shift @$in;
95              
96             # -S
97 286 100       533 if ($arg =~ /^-S$/) {
98 4         10 unshift @style, [ \&ansi_code ];
99 4         10 next;
100             }
101             # -c, -C
102 282 100       551 if ($arg =~ /^-([cC])(.+)?$/) {
103 22 100       71 my $target = $1 eq 'c' ? \@effect : \@style;
104 22 100       81 my($color) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
105 21         60 unshift @$target, [ \&ansi_color, $color ];
106 21         44 next;
107             }
108             # -F
109 260 100       398 if ($arg =~ /^-(F)(.+)?$/) {
110 9 100       28 my($format) = defined $2 ? safe_backslash($2) : $app->retrieve(1);
111 9         21 unshift @style, [ \&ansi_sprintf, $format ];
112 9         17 next;
113             }
114             # -E
115 251 100       379 if ($arg =~ /^-E$/) {
116 5         11 @style = ();
117 5         11 next;
118             }
119              
120             #
121             # -s, -i, -a : ANSI sequence
122             #
123 246 100       555 if ($arg =~ /^-([sia])(.+)?$/) {
    100          
124 18         33 my $opt = $1;
125 18   33     63 my $text = $2 // shift(@$in) // die "Not enough argument.\n";
      50        
126 18         45 my $code = ansi_code($text);
127 18 50       1348 if ($opt eq 's') {
128 0         0 $arg = $code;
129             } else {
130 18 100 100     54 if (@out == 0 or $opt eq 'i') {
131 12         15 push @pending, $code;
132             } else {
133 6         13 $out[-1] .= $code;
134             }
135 18         42 next;
136             }
137             }
138             #
139             # -f : format
140             #
141             elsif ($arg =~ /^-f(.+)?$/) {
142 38 50       156 my($format) = defined $1 ? safe_backslash($1) : $app->retrieve(1);
143             my $n = sum map {
144 37   100     224 { '%' => 0, '*' => 2, '*.*' => 3 }->{$_} // 1
  45         322  
145             } $format =~ /(?| %(%) | %[-+ #0]*+(\*(?:\.\*)?|.) )/xg;
146 37         77 $arg = ansi_sprintf($format, $app->retrieve($n));
147             }
148             #
149             # normal string argument
150             #
151             else {
152 190 100       349 if ($app->escape) {
153 189         893 $arg = safe_backslash($arg);
154             }
155             }
156              
157             #
158             # apply @effect and @style
159             #
160 225         22936 for (splice(@effect), @style) {
161 70         2583 my($func, @opts) = @$_;
162 70         147 $arg = $func->(@opts, $arg);
163             }
164              
165 225         8222 $append->($arg);
166              
167 225 100       453 if ($count) {
168 106         146 my $out = @out + !!@pending;
169 106 50       178 die "Unexpected behavior.\n" if $out > $count;
170 106 100       198 last if $out == $count;
171             }
172             }
173 161 50       248 @pending and $append->();
174 161 100 100     421 die "Not enough argument.\n" if $count and @out < $count;
175 157         708 return @out;
176             }
177              
178             1;
179              
180             __END__