File Coverage

blib/lib/IPC/PrettyPipe/Render/Template/Tiny.pm
Criterion Covered Total %
statement 74 80 92.5
branch 8 12 66.6
condition n/a
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   4038 use Carp;
  4         10  
  4         293  
6 4     4   1015 use Template::Tiny;
  4         2779  
  4         129  
7 4     4   26 use Safe::Isa;
  4         11  
  4         566  
8              
9 4     4   2084 use Text::Tabs qw[ expand ];
  4         3278  
  4         302  
10 4     4   52 use Types::Standard -all;
  4         9  
  4         63  
11 4     4   197153 use Type::Params qw[ validate ];
  4         11  
  4         134  
12              
13 4     4   1173 use Moo;
  4         12  
  4         41  
14              
15              
16             our $VERSION = '0.13';
17              
18             BEGIN {
19 4 50   4   3423 if ( $^O =~ /Win32/i ) {
20 0         0 require Win32::Console::ANSI;
21             }
22             }
23 4     4   3317 use Term::ANSIColor ();
  4         40947  
  4         170  
24              
25 4     4   43 use namespace::clean;
  4         8  
  4         50  
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             has colors => (
52             is => 'rw',
53             isa => HashRef,
54             default => sub {
55             {
56             cmd => {
57             cmd => 'blue',
58             stream => {
59             spec => 'red',
60             file => 'green',
61             },
62             arg => {
63             name => 'red',
64             sep => 'yellow',
65             value => 'green',
66             },
67             },
68             pipe => {
69             stream => {
70             spec => 'red',
71             file => 'green',
72             },
73             },
74             };
75             },
76             );
77              
78              
79              
80              
81              
82              
83              
84              
85              
86              
87              
88              
89              
90              
91              
92             has colorize => (
93             is => 'rw',
94             isa => Bool,
95             default => 1,
96             );
97              
98              
99              
100              
101              
102              
103              
104              
105              
106              
107              
108              
109              
110              
111              
112              
113              
114              
115              
116             has cmd_template => (
117             is => 'rw',
118             default => <<"EOT",
119             [%- indent %][% color.cmd.cmd %][% cmd.quoted_cmd %][% color.reset %]
120             [%- FOREACH arg IN cmd.args.elements %]\\
121             [% indent %][% indent %][% color.cmd.arg.pfx %][% arg.pfx %][% color.cmd.arg.name %][% arg.quoted_name %]
122             [%- IF arg.has_value %][%- IF arg.sep %][% color.cmd.arg.sep %][% arg.sep %][% ELSE %] [% END %]
123             [%- color.cmd.arg.value %][% arg.quoted_value %][% END %][% color.reset %]
124             [%- END %]
125             [%- FOREACH stream IN cmd.streams.elements %]\\
126             [% indent %][% indent %][% color.cmd.stream.spec %][% stream.spec -%]
127             [% IF stream.has_file %] [% color.cmd.stream.file %][% stream.quoted_file %][% color.reset %][% END %]
128             [%- END -%]
129             EOT
130             );
131              
132              
133              
134              
135              
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146              
147              
148              
149             has pipe_template => (
150              
151             is => 'rw',
152              
153             default => <<"EOT",
154             [% indent %][% IF pipe.streams.empty %][% ELSE %](\\
155             [% END %][% cmds %]
156             [%- IF pipe.streams.empty %][% ELSE %]\\
157             [% indent %])[% FOREACH stream IN pipe.streams.elements -%]
158             [% IF stream.first %]\t[% ELSE %]\\
159             \t[% indent %][% END -%]
160             [% color.pipe.stream.spec %][% stream.spec -%]
161             [% IF stream.has_file %] [% color.pipe.stream.file %][% stream.quoted_file %][% color.reset %][% END %]
162             [%- END -%]
163             [%- END -%]
164             EOT
165             );
166              
167             sub _colorize {
168              
169 126     126   424 my ( $tmpl, $colors ) = @_;
170              
171             ## no critic (ProhibitAccessOfPrivateData)
172              
173 126         448 while ( my ( $node, $value ) = each %$tmpl ) {
174              
175 273 100       3378 if ( ref $value ) {
176              
177 105         222 $colors->{$node} = {};
178 105         231 _colorize( $value, $colors->{$node} );
179              
180             }
181              
182             else {
183 168         376 $colors->{$node} = Term::ANSIColor::color( $value );
184             }
185              
186             }
187              
188             }
189              
190              
191              
192              
193              
194              
195              
196              
197              
198              
199              
200              
201              
202              
203              
204              
205              
206              
207              
208             sub render {
209              
210 21     21 1 245 my $self = shift;
211              
212 21         106 my ( $pipe, $args ) = validate(
213             \@_,
214             InstanceOf[ 'IPC::PrettyPipe' ],
215             slurpy Dict [
216             colorize => Optional [Bool],
217             ] );
218              
219             $args->{colorize} = $self->colorize ## no critic (ProhibitAccessOfPrivateData)
220 21 50       99019 unless exists $args->{colorize};
221              
222 21         4306 my %color;
223 21         453 _colorize( $self->colors, \%color );
224              
225 21 50       528 $color{reset} = Term::ANSIColor::color( 'reset' )
226             if keys %color;
227              
228 21         411 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 21         50 my @output;
233 21         134 $self->_render_pipe( $pipe, { indent => '' }, \@output );
234              
235 21         83 my @records = map { expand( $_ ) } map { split( /\n/, $_ ) } @output;
  85         2004  
  21         95  
236 21         618 my @lengths = map { length } @records;
  85         158  
237 21         98 my $max = List::Util::max( @lengths ) + 4;
238              
239 21 50       74 if ( $args->{colorize} ) {
240 0         0 @output = ();
241 0         0 $self->_render_pipe( $pipe, { indent => '', color => \%color },
242             \@output );
243 0         0 @records = map { expand( $_ ) } map { split( /\n/, $_ ) } @output;
  0         0  
  0         0  
244             }
245              
246 21         47 foreach ( @records ) {
247 85         184 my $pad = ' ' x ( $max - shift @lengths );
248 85         358 s/\\$/$pad \\/;
249             }
250              
251 21         231 return join( "\n", @records ) . "\n";
252             }
253              
254             sub _render_pipe {
255              
256 23     23   50 my $self = shift;
257              
258 23         56 my ( $pipe, $process_args, $output ) = @_;
259              
260 23         40 my %process_args = %{$process_args};
  23         127  
261              
262 23         55 my @output;
263              
264 23         40 for my $cmd ( @{ $pipe->cmds->elements } ) {
  23         110  
265 32 100       890 if ( $cmd->isa( 'IPC::PrettyPipe' ) ) {
266 2         10 local $process_args{indent} = $process_args{indent} . "\t";
267 2         12 $self->_render_pipe( $cmd, \%process_args, \@output );
268             }
269             else {
270 30         103 local $process_args{indent} = $process_args{indent} . "\t";
271 30         61 push @output, '';
272 30         71 local $process_args{cmd} = $cmd;
273 30         146 Template::Tiny->new->process( \$self->cmd_template, \%process_args,
274             \( $output[-1] ) );
275             }
276             }
277              
278 23         1666 $process_args{cmds} = join( "\\\n|", @output );
279 23         59 $process_args{pipe} = $pipe;
280 23         47 push @{$output}, '';
  23         50  
281 23         76 Template::Tiny->new->process( \$self->pipe_template, \%process_args,
282             \( $output->[-1] ) );
283 23         2270 return;
284             }
285              
286              
287             with 'IPC::PrettyPipe::Renderer';
288              
289             1;
290              
291             #
292             # This file is part of IPC-PrettyPipe
293             #
294             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
295             #
296             # This is free software, licensed under:
297             #
298             # The GNU General Public License, Version 3, June 2007
299             #
300              
301             __END__