File Coverage

blib/lib/IPC/PrettyPipe/Render/Template/Tiny.pm
Criterion Covered Total %
statement 74 80 92.5
branch 7 10 70.0
condition 1 2 50.0
subroutine 13 13 100.0
pod 1 1 100.0
total 96 106 90.5


line stmt bran cond sub pod time code
1             package IPC::PrettyPipe::Render::Template::Tiny;
2              
3             # ABSTRACT: rendering backend using B
4              
5 4     4   2137 use Carp;
  4         11  
  4         261  
6 4     4   493 use Template::Tiny;
  4         1336  
  4         106  
7 4     4   22 use Safe::Isa;
  4         8  
  4         473  
8              
9 4     4   1792 use Text::Tabs qw[ expand ];
  4         2819  
  4         241  
10 4     4   26 use Types::Standard -all;
  4         10  
  4         52  
11 4     4   176071 use Type::Params qw[ validate ];
  4         11  
  4         41  
12              
13 4     4   991 use Moo;
  4         11  
  4         37  
14              
15              
16             our $VERSION = '0.12';
17              
18             BEGIN {
19 4 50   4   2817 if ( $^O =~ /Win32/i ) {
20 0         0 require Win32::Console::ANSI;
21             }
22             }
23 4     4   2728 use Term::ANSIColor ();
  4         33264  
  4         134  
24              
25 4     4   33 use namespace::clean;
  4         8  
  4         33  
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51              
52             has pipe => (
53             is => 'rw',
54             isa => InstanceOf ['IPC::PrettyPipe'],
55             required => 1,
56             );
57              
58              
59              
60              
61              
62              
63              
64              
65              
66              
67              
68              
69              
70              
71              
72              
73             has colors => (
74             is => 'rw',
75             isa => HashRef,
76             default => sub {
77             {
78             cmd => {
79             cmd => 'blue',
80             stream => {
81             spec => 'red',
82             file => 'green',
83             },
84             arg => {
85             name => 'red',
86             sep => 'yellow',
87             value => 'green',
88             },
89             },
90             pipe => {
91             stream => {
92             spec => 'red',
93             file => 'green',
94             },
95             },
96             };
97             },
98             );
99              
100              
101              
102              
103              
104              
105              
106              
107              
108              
109              
110              
111              
112              
113              
114              
115              
116              
117              
118             has cmd_template => (
119             is => 'rw',
120             default => <<"EOT",
121             [%- indent %][% color.cmd.cmd %][% cmd.quoted_cmd %][% color.reset %]
122             [%- FOREACH arg IN cmd.args.elements %]\\
123             [% indent %][% indent %][% color.cmd.arg.pfx %][% arg.pfx %][% color.cmd.arg.name %][% arg.quoted_name %]
124             [%- IF arg.has_value %][%- IF arg.sep %][% color.cmd.arg.sep %][% arg.sep %][% ELSE %] [% END %]
125             [%- color.cmd.arg.value %][% arg.quoted_value %][% END %][% color.reset %]
126             [%- END %]
127             [%- FOREACH stream IN cmd.streams.elements %]\\
128             [% indent %][% indent %][% color.cmd.stream.spec %][% stream.spec -%]
129             [% IF stream.has_file %] [% color.cmd.stream.file %][% stream.quoted_file %][% color.reset %][% END %]
130             [%- END -%]
131             EOT
132             );
133              
134              
135              
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146              
147              
148              
149              
150              
151             has pipe_template => (
152              
153             is => 'rw',
154              
155             default => <<"EOT",
156             [% indent %][% IF pipe.streams.empty %][% ELSE %](\\
157             [% END %][% cmds %]
158             [%- IF pipe.streams.empty %][% ELSE %]\\
159             [% indent %])[% FOREACH stream IN pipe.streams.elements -%]
160             [% IF stream.first %]\t[% ELSE %]\\
161             \t[% indent %][% END -%]
162             [% color.pipe.stream.spec %][% stream.spec -%]
163             [% IF stream.has_file %] [% color.pipe.stream.file %][% stream.quoted_file %][% color.reset %][% END %]
164             [%- END -%]
165             [%- END -%]
166             EOT
167             );
168              
169             sub _colorize {
170              
171 120     120   399 my ( $tmpl, $colors ) = @_;
172              
173             ## no critic (ProhibitAccessOfPrivateData)
174              
175 120         400 while ( my ( $node, $value ) = each %$tmpl ) {
176              
177 260 100       3306 if ( ref $value ) {
178              
179 100         203 $colors->{$node} = {};
180 100         212 _colorize( $value, $colors->{$node} );
181              
182             }
183              
184             else {
185 160         349 $colors->{$node} = Term::ANSIColor::color( $value );
186             }
187              
188             }
189              
190             }
191              
192              
193              
194              
195              
196              
197              
198              
199              
200              
201              
202              
203              
204              
205              
206              
207              
208              
209              
210             sub render {
211              
212 20     20 1 2702 my $self = shift;
213              
214 20         117 my ( $args ) = validate(
215             \@_,
216             slurpy Dict [
217             colorize => Optional [Bool],
218             ] );
219              
220 20   50     39901 $args->{colorize} //= 1; ## no critic (ProhibitAccessOfPrivateData)
221              
222 20         2160 my %color;
223 20         538 _colorize( $self->colors, \%color );
224              
225 20 50       452 $color{reset} = Term::ANSIColor::color( 'reset' )
226             if keys %color;
227              
228 20         378 local $Text::Tabs::tabstop = 2;
229              
230             # generate non-colorized version so can get length of records to
231             # pad out any continuation lines
232 20         38 my @output;
233 20         452 $self->_render_pipe( $self->pipe, { indent => '' }, \@output);
234              
235 20         79 my @records = map { expand( $_ ) } map { split( /\n/, $_ ) } @output;
  77         1900  
  20         86  
236 20         649 my @lengths = map { length } @records;
  77         156  
237 20         99 my $max = List::Util::max( @lengths ) + 4;
238              
239 20 50       76 if ( $args->{colorize} ) {
240 0         0 @output = ();
241 0         0 $self->_render_pipe( $self->pipe, { indent => '', color => \%color }, \@output);
242 0         0 @records = map { expand( $_ ) } map { split( /\n/, $_ ) } @output;
  0         0  
  0         0  
243             }
244              
245 20         52 foreach ( @records ) {
246 77         178 my $pad = ' ' x ($max - shift @lengths);
247 77         493 s/\\$/$pad \\/;
248             }
249              
250 20         280 return join ("\n", @records ) . "\n";
251             }
252              
253             sub _render_pipe {
254              
255 22     22   250 my $self = shift;
256              
257 22         56 my ( $pipe, $process_args, $output ) = @_;
258              
259 22         37 my %process_args = %{$process_args};
  22         91  
260              
261 22         42 my @output;
262              
263 22         48 for my $cmd ( @{ $pipe->cmds->elements } ) {
  22         105  
264 30 100       772 if ( $cmd->isa( 'IPC::PrettyPipe' ) ) {
265 2         7 local $process_args{indent} = $process_args{indent} . "\t";
266 2         11 $self->_render_pipe( $cmd, \%process_args, \@output );
267             }
268             else {
269 28         96 local $process_args{indent} = $process_args{indent} . "\t";
270 28         68 push @output, '';
271 28         65 local $process_args{cmd} = $cmd;
272 28         122 Template::Tiny->new->process( \$self->cmd_template, \%process_args,
273             \( $output[-1] ) );
274             }
275             }
276              
277 22         1874 $process_args{cmds} = join( "\\\n|", @output );
278 22         59 $process_args{pipe} = $pipe;
279 22         44 push @{$output}, '';
  22         58  
280 22         120 Template::Tiny->new->process( \$self->pipe_template, \%process_args,
281             \( $output->[-1] ) );
282 22         1994 return;
283             }
284              
285              
286             with 'IPC::PrettyPipe::Renderer';
287              
288             1;
289              
290             #
291             # This file is part of IPC-PrettyPipe
292             #
293             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
294             #
295             # This is free software, licensed under:
296             #
297             # The GNU General Public License, Version 3, June 2007
298             #
299              
300             __END__