File Coverage

blib/lib/App/optex/pingu.pm
Criterion Covered Total %
statement 29 63 46.0
branch 0 12 0.0
condition 0 7 0.0
subroutine 10 15 66.6
pod 0 4 0.0
total 39 101 38.6


[RGBCMYWK])\g{col}*) }{
line stmt bran cond sub pod time code
1             package App::optex::pingu;
2              
3             my $VERSION = '0.03';
4              
5 1     1   626 use v5.14;
  1         3  
6 1     1   4 use warnings;
  1         1  
  1         19  
7 1     1   520 use utf8;
  1         12  
  1         4  
8 1     1   26 use Carp;
  1         2  
  1         70  
9 1     1   438 use open IO => 'utf8', ':std';
  1         1022  
  1         5  
10 1     1   564 use Data::Dumper;
  1         5679  
  1         74  
11              
12             =encoding utf8
13              
14             =head1 NAME
15              
16             pingu - optex make-everything-pingu filter
17              
18             =head1 SYNOPSIS
19              
20             B -Mpingu --pingu I
21              
22             =head1 DESCRIPTION
23              
24             This B module is greatly inspired by L command and
25             make every command pingu not only L. As for original
26             command, see L section. All honor for this idea should go
27             to the original author.
28              
29             =begin html
30              
31            

32              
33             =end html
34              
35             =begin html
36              
37            

38              
39             =end html
40              
41             This module is a quite good example to demonstrate L command
42             features.
43              
44             =head1 OPTION
45              
46             =over 7
47              
48             =item B<--pingu>
49              
50             Make command pingu.
51              
52             =item B<--pingu-image>=I
53              
54             Set image file. File is searched at current directory and module
55             directory. Standard B image is stored as B. If
56             string C is specified, module search the file in the following
57             order.
58              
59             ./pingu
60             ./pingu.asc
61             module-dir/pingu
62             module-dir/pingu.asc
63              
64             =item B<--pingu-char>
65              
66             Specify replacement character. Default is Unicode C
67             (U+2588: █).
68              
69             =item B<--pingu-interval>=I
70              
71             Set interval time between printing each lines. Default is zero.
72              
73             =back
74              
75             =head1 IMAGE FILE FORMAT
76              
77             =over 4
78              
79             =item ASCII
80              
81             Each [C] character is converted to specified letter
82             with color which the character itself describe. Upper-case character
83             represent normal ANSI color and lower-case means high-intensity color.
84              
85             R r Red
86             G g Green
87             B b Blue
88             C c Cyan
89             M m Magenta
90             Y y Yellow
91             K k Black
92             W w White
93              
94             Line start with C<#> is treated as a comment.
95              
96             Default pingu image:
97              
98             ... . ... .. .. .........
99             ... .... .. .. ... ..... .. ..
100             ... ....... ... ... . ..... kkkkkkk
101             ..... ........ .kkkkkkkkkkkkkkk..... ... kkkkkkkkkk. .
102             .... ........kkkkkkkkkkkkkkkkkkkkk. ... kkkkkkkkkkk
103             ....... kkwwwwkkkkkkkkkkkkkkkk.... kkkkkkkkkkkk
104             . . .... kkwwkkwwkkkkkkkkkkwwwwkk... kkkkkkkkkkk
105             .. ....kkkkwwwwkkrrrrrrkkwwkkwwk.. .kkkkkkkkkkk
106             . kkkkkkkkrrrrrrrrrrkwwwwkk. .kkkkkkkkkk
107             .... .kkkkkkkkrrrrrrrrkkkkkkkk. kkkkkkkk
108             ..... . kkkkkkkkkkkkkkkkkkkk. kkkkkkk.
109             ...... .. . kkkkkkkkkkkkkkkkkk . . .kkkkkkk
110             ...... kkkkkkkkkkkkkkkkkkkkk . .kkkkkkk
111             ...... .kkkkkkkkkkkkkkkkkkyywwkkkkk .. kkkkkkk
112             ... . kkkkkkkkkkkkkkkkywwwwwwwwwkkkkkkkkkkkkkk.
113             kkkkkkkkkkkkkkkkywwwwwwwwwwwwwkkkkkkkkk .
114             kkkkkkkkkkkkkkkywwwwwwwwwwwwwwwwkk .
115             kkkkkkkkkkkkkkkywwwwwwwwwwwwwwwwwww ........
116             .kkkkkkkkkkkkkkkkywwwwwwwwwwwwwwwwwwww .........
117             .kkkkkkkkkkkkkkkkywwwwwwwwwwwwwwwwwwwwww .... . .
118              
119             =back
120              
121             Other file format is not supported yet.
122              
123             Coloring is done by L module. See its document
124             for detail.
125              
126             =head1 INSTALL
127              
128             Use L command:
129              
130             cpanm App::optex::pingu
131              
132             =head1 PINGU ALIAS
133              
134             You can set shell alias B to call L command through
135             B.
136              
137             alias pingu='optex -Mpingu --pingu ping'
138              
139             However, there is more sophisticated way to use B alias
140             function. Next command will make symbolic link C<< pingu->optex >> in
141             F<~/.optex.d/bin> directory:
142              
143             $ optex --ln pingu
144              
145             Executing this symbolic link, optex will call system installed
146             B command. So make an alias in F<~/.optex.d/config.toml> to
147             call L command instead:
148              
149             [alias]
150             pingu = "ping -Mpingu --pingu"
151              
152             =head1 MAKING NEW PING OPTION
153              
154             You can add, say, B<--with-pingu> option to the original L
155             command. Make a symbolic link C<< ping->optex >> in F<~/.optex.d/bin>
156             directory:
157              
158             $ optex --ln ping
159              
160             And create an rc file F<~/.optex.d/ping.rc> for B:
161              
162             option --with-pingu -Mpingu --pingu
163              
164             Then pingu will show up when you use B<--with-pingu> option to execute
165             L command:
166              
167             $ ping --with-pingu localhost -c15
168              
169             If you want to enable this option always (really?), put next line in
170             your F<~/.optex.d/ping.rc>:
171              
172             option default --with-pingu
173              
174             =head1 SEE ALSO
175              
176             L
177              
178             L,
179             L
180              
181             L,
182             L
183              
184             =head1 AUTHOR
185              
186             Kazumasa Utashiro
187              
188             =head1 LICENSE
189              
190             Copyright 2022 Kazumasa Utashiro.
191              
192             You can redistribute it and/or modify it under the same terms
193             as Perl itself.
194              
195             =cut
196              
197 1     1   345 use File::Share qw(dist_dir);
  1         22470  
  1         49  
198 1     1   6 use List::Util qw(first);
  1         1  
  1         76  
199 1     1   500 use Getopt::EX::Colormap qw(colorize);
  1         17960  
  1         61  
200 1     1   463 use Time::HiRes qw(usleep);
  1         1145  
  1         3  
201              
202             my $image_dir = $ENV{OPTEX_PINGU_IMAGEDIR} //= dist_dir 'App-optex-pingu';
203              
204             our %param = (
205             char => '█',
206             repeat => 1,
207             interval => 0,
208             );
209              
210             my %reader = (
211             asc => \&read_asc,
212             );
213              
214             sub get_image {
215 0     0 0   my $name = shift;
216 0           my $file = do {
217 0     0     first { -s }
218             map {
219 0           my $dir = $_;
  0            
220 0           map { "${dir}${name}$_" } '', '.asc';
  0            
221             } '', "$image_dir/";
222             };
223 0 0         die "$name: image file not found.\n" unless $file;
224 0   0       my $type = ($file =~ /\.(\w+$)/)[0] || 'asc';
225 0   0       my $reader = $reader{$type} // $reader{'asc'};
226 0           $reader->($file);
227             }
228              
229             sub read_asc {
230 0     0 0   my $file = shift;
231 0 0         open my $fh, '<', $file or die "$file: $!\n";
232 0           local $_ = do { local $/; <$fh> };
  0            
  0            
233 0           s/^#.*\n//mg;
234 0           s{ (?(?
235 0           colorize($+{col}, $param{char} x length($+{str}))
236             }xgie;
237 0           /.+/g;
238             }
239              
240             sub pingu {
241 0 0   0 0   @_ = map { utf8::is_utf8($_) ? $_ : decode('utf8', $_) } @_;
  0            
242 0           my %opt = @_;
243 0   0       my $name = $opt{name} || 'pingu';
244 0           my @image = get_image($name);
245 0           my $i = 0;
246 0 0         my $sleep = $param{interval} > 0 ? $param{interval} * 1000000 : 0;
247 0           while (<>) {
248 0           print $image[$i++ % @image], $_;
249 0 0         usleep $sleep if $sleep > 0;
250             }
251             }
252              
253             sub set {
254 0     0 0   while (my($k, $v) = splice(@_, 0, 2)) {
255 0 0         exists $param{$k} or next;
256 0           $param{$k} = $v;
257             }
258 0           ();
259             }
260              
261             1;
262              
263             __DATA__