File Coverage

blib/lib/Term/YAP.pm
Criterion Covered Total %
statement 50 60 83.3
branch 4 12 33.3
condition n/a
subroutine 12 15 80.0
pod 3 3 100.0
total 69 90 76.6


line stmt bran cond sub pod time code
1             package Term::YAP;
2              
3 9     9   521089 use strict;
  9         18  
  9         237  
4 9     9   88 use warnings;
  9         16  
  9         300  
5              
6             =head1 NAME
7              
8             Term::YAP - show pulsed progress bar in terminal
9              
10             =cut
11              
12 9     9   1825 use Types::Standard qw(Str Int Bool Num);
  9         133820  
  9         106  
13 9     9   10751 use Time::HiRes qw(usleep time);
  9         4770  
  9         70  
14 9     9   3143 use Moo;
  9         27453  
  9         74  
15 9     9   27371 use namespace::clean;
  9         18415  
  9         61  
16              
17             our $VERSION = "0.03";
18              
19             =head1 SYNOPSIS
20              
21             use Term::YAP;
22            
23             my $yap = Term::YAP->new( { name => 'Checking', rotate => 0, time => 1 } );
24            
25             $yap->start(); # start the pulse
26             # do something between
27             $yap->stop() # stop it
28              
29             =head1 DESCRIPTION
30              
31             Term::YAP is a L<Moo> based class to implement a "pulse" bar in a terminal. A pulse bar does not shows any progress of the task being executed
32             but at least shows that the program is working instead of showing nothing for user.
33              
34             This is the parent class and some methods were not implemented, you probably want to look for subclasses to get an implementation.
35              
36             This module was shamelessly copied from L<Term::Pulse>. Sorry, couldn't get my bug/patch approved. :-)
37              
38             =head1 EXPORT
39              
40             Nothing.
41              
42             =head1 ATTRIBUTES
43              
44             All attributes are optional and have their respective default values.
45              
46             =head2 name
47              
48             A simple message displayed before the pulse. The default value is 'Working'.
49              
50             =cut
51              
52             has name =>
53             ( is => 'ro', isa => Str, default => 'Working', reader => 'get_name' );
54              
55             =head2 rotatable
56              
57             Boolean. Rotates the pulse if set to true. It is false by default.
58              
59             =cut
60              
61             has rotatable =>
62             ( is => 'ro', isa => Bool, default => 0, reader => 'is_rotatable' );
63              
64             =head2 time
65              
66             Boolean. Display the elapsed time if set to 1. Turn off by default.
67              
68             =cut
69              
70             has time => ( is => 'ro', isa => Bool, default => 0, reader => 'show_time' );
71              
72             =head2 size
73              
74             Set the pulse size. The default value is 16.
75              
76             =cut
77              
78             has size => ( is => 'ro', isa => Int, default => 16, reader => 'get_size' );
79              
80             =head2 start_time
81              
82             The time (Unix Epoch) that the pulse bar started in seconds.
83              
84             This attribute is "private".
85              
86             =cut
87              
88             has start_time => (
89             is => 'rw',
90             isa => Num,
91             reader => '_get_start',
92             writer => '_set_start',
93             );
94              
95             =head2 usleep
96              
97             The microseconds elapsed that each pulse has between each other. The default value is 200000.
98              
99             This attribute is "private".
100              
101             =cut
102              
103             has usleep =>
104             ( is => 'ro', isa => Num, reader => '_get_usleep', default => 200000 );
105              
106             =head2 running
107              
108             Boolean. If true, the pulse was started, false otherwise.
109              
110             =cut
111              
112             has running => (
113             is => 'ro',
114             isa => Bool,
115             reader => 'is_running',
116             writer => '_set_running',
117             default => 0
118             );
119              
120             =head1 METHODS
121              
122             =head2 is_running
123              
124             Getter for C<running> attribute.
125              
126             =head2 BUILD
127              
128             Install handlers for signals C<INT> and C<__DIE__>.
129              
130             =cut
131              
132             sub BUILD {
133              
134 6     6 1 162 my $self = shift;
135              
136 6     0   156 $SIG{INT} = sub { $self->stop };
  0         0  
137 6     0   162 $SIG{__DIE__} = sub { $self->stop };
  0         0  
138              
139             }
140              
141             =head2 get_name
142              
143             Returns the value of the name attribute.
144              
145             =head2 is_rotatable
146              
147             Returns the value of rotatable attribute.
148              
149             =head2 show_time
150              
151             Returns the value of time attribute.
152              
153             =head2 get_size
154              
155             Returns the value of size attribute.
156              
157             =head2 start
158              
159             Starts the pulse. Returns the value of C<running> attribute.
160              
161             =cut
162              
163             sub start {
164              
165 15     15 1 55 my $self = shift;
166 15         642 return $self->is_running();
167              
168             }
169              
170             sub _is_enough {
171              
172 0     0   0 die '_is_enough() method must be overrided by subclasses of Term::YAP';
173              
174             }
175              
176             sub _keep_pulsing {
177              
178 5     5   210 my $self = shift;
179              
180 5         160 my @mark = qw(- \ | / - \ | /);
181 5         170 $| = 1;
182              
183 5         290 my $name = $self->get_name();
184 5         282 my $rotate = $self->is_rotatable();
185 5         248 my $size = $self->get_size();
186 5         397 my $time = $self->show_time();
187 5         255 my $start = time();
188 5         158 $self->_set_start($start);
189              
190 5         12994 INFINITE: while (1) {
191              
192             # forward
193 5         195 foreach my $index ( 1 .. $size ) {
194              
195 80 50       8296 my $mark = $rotate ? $mark[ $index % 8 ] : q{=};
196 80         8266 printf "$name...[%s%s%s]", q{ } x ( $index - 1 ), $mark,
197             q{ } x ( $size - $index );
198 80 50       4387 printf " (%f sec elapsed)", ( time - $start ) if $time;
199 80         1379 printf "\r";
200 80 100       8232 last INFINITE if ( $self->_is_enough() );
201 75         683 $self->_sleep();
202             }
203              
204             # backward
205 0         0 foreach my $index ( 1 .. $size ) {
206              
207 0 0       0 my $mark = $rotate ? $mark[ ( $index % 8 ) * -1 ] : q{=};
208 0         0 printf "$name...[%s%s%s]", q{ } x ( $size - $index ), $mark,
209             q{ } x ( $index - 1 );
210 0 0       0 printf " (%f sec elapsed)", ( time - $start ) if $time;
211 0         0 printf "\r";
212 0 0       0 last INFINITE if ( $self->_is_enough() );
213 0         0 $self->_sleep();
214              
215             }
216              
217             }
218              
219 5         175 return ( time() - $self->_get_start() );
220              
221             }
222              
223             =head2 stop
224              
225             Stop the pulse and return elapsed time.
226              
227             =cut
228              
229             sub stop {
230              
231 15     15 1 55 my $self = shift;
232 15         229 return $self->_report;
233              
234             }
235              
236             sub _report {
237              
238 15     15   53 my $self = shift;
239 15         220 my $name = $self->get_name();
240 15         70 my $length = length($name);
241 15         1064 printf "$name%sDone%s\n", q{.} x ( 35 - $length ), q{ } x 43;
242 15         160 return 1;
243              
244             }
245              
246             sub _sleep {
247              
248 90     90   322 my $self = shift;
249 90         17961527 usleep( $self->_get_usleep() );
250              
251             }
252              
253             =head1 SEE ALSO
254              
255             =over
256              
257             =item *
258              
259             L<Term::Pulse>
260              
261             =item *
262              
263             L<Moo>
264              
265             =back
266              
267             =head1 AUTHOR
268              
269             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
270              
271             L<Term::Pulse> was originally created by Yen-Liang Chen, E<lt>alec at cpan.comE<gt>
272              
273             =head1 COPYRIGHT AND LICENSE
274              
275             This software is copyright (c) 2015 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
276              
277             This file is part of Term-YAP distribution.
278              
279             Term-YAP is free software: you can redistribute it and/or modify
280             it under the terms of the GNU General Public License as published by
281             the Free Software Foundation, either version 3 of the License, or
282             (at your option) any later version.
283              
284             Term-YAP is distributed in the hope that it will be useful,
285             but WITHOUT ANY WARRANTY; without even the implied warranty of
286             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287             GNU General Public License for more details.
288              
289             You should have received a copy of the GNU General Public License
290             along with Term-YAP. If not, see <http://www.gnu.org/licenses/>.
291              
292             =cut
293              
294             1;