File Coverage

blib/lib/Term/Spinner/Lite.pm
Criterion Covered Total %
statement 80 85 94.1
branch 22 26 84.6
condition 1 2 50.0
subroutine 18 20 90.0
pod 7 7 100.0
total 128 140 91.4


line stmt bran cond sub pod time code
1 2     2   44547 use strict;
  2         5  
  2         71  
2 2     2   10 use warnings;
  2         5  
  2         109  
3             package Term::Spinner::Lite;
4             {
5             $Term::Spinner::Lite::VERSION = '0.03';
6             }
7              
8             # ABSTRACT: A spinner without so much Moose in it
9              
10 2     2   51 use 5.010;
  2         12  
  2         78  
11 2     2   1988 use IO::Handle;
  2         26949  
  2         132  
12 2     2   2204 use Time::HiRes qw(usleep);
  2         5751  
  2         16  
13 2     2   613 use Carp qw( croak );
  2         5  
  2         5810  
14              
15              
16              
17             sub new {
18 1     1 1 229 my ($class, %args) = @_;
19              
20 1         6 my $self = bless \%args, $class;
21              
22 1         5 $self->_setup_signal_handler;
23              
24 1         4 return $self;
25             }
26              
27             # We need to restore the cursor if the user hits Contol-C or a TERM signal
28             sub _setup_signal_handler {
29 1     1   3 my $self = shift;
30              
31 1     0   31 $SIG{INT} = sub { $self->done; exit 0; };
  0         0  
  0         0  
32 1     0   16 $SIG{TERM} = sub { $self->done; exit 0; };
  0         0  
  0         0  
33             }
34              
35              
36             sub output_handle {
37 25     25 1 30 my $self = shift;
38 25         29 my $handle = shift;
39 25   50     96 my $encoding = shift || ":utf8";
40              
41 25 50       50 if ( not $handle ) {
42 25 100       289 if ( exists $self->{'output_handle'} ) {
43 24         656 return $self->{'output_handle'};
44             }
45 1         2 $handle = \*STDERR;
46             }
47              
48 1         7 binmode($handle, $encoding);
49 1         12 $handle->autoflush(1);
50              
51 1         68 $self->{'output_handle'} = $handle;
52             }
53              
54              
55             sub spin_chars {
56 13     13 1 18 my $self = shift;
57 13         17 my $aref = shift;
58              
59 13 100       25 if ( not $aref ) {
60 12 100       32 if ( exists $self->{'spin_chars'} ) {
61 11         142 return $self->{'spin_chars'};
62             }
63 1         4 $aref = [ qw(- \ | /) ];
64             }
65            
66 2 50       6 if ( ref($aref) ne 'ARRAY' ) {
67 0         0 croak "spin_chars must be an array ref";
68             }
69              
70 2         15 $self->{'spin_chars'} = $aref;
71             }
72              
73              
74             sub delay {
75 22     22 1 25 my $self = shift;
76 22         28 my $microseconds = shift;
77              
78 22 100       213 if ( not $microseconds ) {
79 21 100       47 if ( exists $self->{'delay'} ) {
80 20         11315 return $self->{'delay'};
81             }
82 1         2 $microseconds = 0;
83             }
84              
85 2         10 $self->{'delay'} = $microseconds;
86             }
87              
88             sub _clear {
89 10     10   22 my $self = shift;
90              
91 10         12 print {$self->output_handle()} "\010 \010";
  10         28  
92             }
93              
94             # https://github.com/verigak/progress/blob/master/progress/helpers.py#L19
95             sub _show_cursor {
96 1     1   3 my $self = shift;
97              
98 1         3 print {$self->output_handle()} "\x1b[?25h";
  1         5  
99             }
100              
101             # https://github.com/verigak/progress/blob/master/progress/helpers.py#L18
102             sub _hide_cursor {
103 4     4   31 my $self = shift;
104              
105 4         7 print {$self->output_handle()} "\x1b[?25l";
  4         11  
106             }
107              
108             sub _spin_char_size {
109 11     11   403 my $self = shift;
110              
111 11 100       29 if ( exists $self->{'spin_char_size'} ) {
112 10         113 return $self->{'spin_char_size'};
113             }
114              
115 1         4 $self->{'spin_char_size'} = scalar @{ $self->spin_chars() };
  1         3  
116             }
117              
118              
119             sub count {
120 12     12 1 20 my $self = shift;
121              
122 12 100       43 return 0 if not exists $self->{'count'};
123              
124 10         50 return $self->{'count'};
125             }
126              
127              
128             sub next {
129 10     10 1 51 my $self = shift;
130              
131 10         11 state $pos = 0;
132              
133 10 100       20 $self->_clear if $self->count;
134 10 100       34 $self->_hide_cursor if not $pos;
135 10         12 print {$self->output_handle()} "${$self->spin_chars()}[$pos]";
  10         24  
  10         22  
136 10         36 $pos = ($self->{'count'}++) % $self->_spin_char_size();
137 10 50       22 usleep($self->delay) if $self->delay;
138             }
139              
140              
141             sub done {
142 1     1 1 15 my $self = shift;
143              
144 1         6 $self->_clear;
145 1         7 $self->_show_cursor;
146 1 50       8 print "\n" if $_[0];
147             }
148              
149             1;
150              
151             __END__