File Coverage

blib/lib/Term/Output/List/ANSI.pm
Criterion Covered Total %
statement 32 59 54.2
branch 3 14 21.4
condition 1 2 50.0
subroutine 8 10 80.0
pod 4 4 100.0
total 48 89 53.9


line stmt bran cond sub pod time code
1             package Term::Output::List::ANSI;
2 2     2   1197 use strict;
  2         21  
  2         61  
3 2     2   10 use warnings;
  2         5  
  2         52  
4 2     2   1239 use Moo 2;
  2         24864  
  2         10  
5 2     2   4473 use Term::Cap;
  2         6170  
  2         73  
6 2     2   13 use feature 'signatures';
  2         4  
  2         177  
7 2     2   12 no warnings 'experimental::signatures';
  2         3  
  2         1382  
8              
9             our $VERSION = '0.03';
10              
11             =head1 NAME
12              
13             Term::Output::List::ANSI - output an updateable list of ongoing jobs to an ANSI terminal
14              
15             =head1 SYNOPSIS
16              
17             my $printer = Term::Output::List->new();
18             my @ongoing_tasks = ('file1: frobnicating', 'file2: bamboozling', 'file3: frobnicating');
19             $printer->output_list(@ongoing_tasks);
20              
21             $printer->output_permanent("Frobnicated gizmos"); # appears above the list
22              
23             =cut
24              
25             has '_last_lines' => (
26             is => 'rw',
27             );
28              
29             =head1 MEMBERS
30              
31             =head2 C<< fh >>
32              
33             Filehandle used for output. Default is C<< STDOUT >>.
34              
35             =cut
36              
37             has 'fh' => (
38             is => 'lazy',
39             default => sub { \*STDOUT },
40             );
41              
42             has 'terminfo' => (
43             is => 'lazy',
44             default => sub { Term::Cap->Tgetent({ OSPEED => 112000 })},
45             );
46              
47             has 'term_scroll_up' => (
48             is => 'lazy',
49             default => sub { $_[0]->terminfo->Tputs('UP') },
50             );
51              
52             has 'term_clear_eol' => (
53             is => 'lazy',
54             default => sub { $_[0]->terminfo->Tputs('ce') },
55             );
56              
57             has 'interactive' => (
58             is => 'lazy',
59             default => sub { -t $_[0]->fh },
60             );
61              
62             =head2 C<< width >>
63              
64             Width of the terminal. This is initialized at first use. You may (or may not)
65             want to set up a C<< $SIG{WINCH} >> handler to set the terminal width when
66             the terminal size changes.
67              
68             =cut
69              
70             has 'width' => (
71             is => 'lazy',
72             default => sub { `tput cols` },
73             );
74              
75             =head1 METHODS
76              
77             =head2 C<< Term::Output::List->new() >>
78              
79             =cut
80              
81             =head2 C<< ->scroll_up >>
82              
83             Helper method to place the cursor at the top of the updateable list.
84              
85             =cut
86              
87 0     0 1 0 sub scroll_up( $self, $count=$self->_last_lines ) {
  0         0  
  0         0  
  0         0  
88 0 0       0 if( !$count) {
89             } else {
90             # Overwrite the number of lines we printed last time
91 0         0 print { $self->fh } "\r" . sprintf $self->term_scroll_up(), ${count};
  0         0  
92             #sleep 1;
93             };
94             }
95              
96             =head2 C<< ->output_permanent >>
97              
98             $o->output_permanent("Frobnicated 3 items for job 2");
99             $o->output_list("Frobnicating 9 items for job 1",
100             "Frobnicating 2 items for job 3",
101             );
102              
103             Outputs items that should go on the permanent record. It is expected to
104             output the (remaining) list of ongoing jobs after that.
105              
106             =cut
107              
108 10     10 1 3188 sub output_permanent( $self, @items ) {
  10         16  
  10         22  
  10         14  
109 10   50     45 my $total = $self->_last_lines // 0;
110 10 50       168 if( $self->interactive ) {
111 0         0 $self->scroll_up();
112 0         0 my $w = $self->width;
113 0         0 my $clear_eol = $self->term_clear_eol;
114 0 0       0 if( @items ) {
115 0         0 print { $self->fh }
116             join("$clear_eol\n",
117 0 0       0 map { length($_) > $w - 1 ? (substr($_,0,$w-3).'..'): $_
  0         0  
118             } @items)."$clear_eol\n";
119             };
120             } else {
121 10         70 print { $self->fh } join("\n", @items) . "\n";
  10         157  
122             }
123             #sleep 1;
124              
125 10 50       352 if( $self->interactive ) {
126 0         0 my $blank = $total - @items;
127 0         0 my $clear_eol = $self->term_clear_eol;
128 0 0       0 if( $blank > 0 ) {
129 0         0 print { $self->fh } "$clear_eol\n"x ($blank);
  0         0  
130 0         0 $self->scroll_up( $blank );
131             }
132 0         0 $self->fresh_output();
133             }
134             }
135              
136             =head2 C<< ->output_list @items >>
137              
138             $o->output_list("Frobnicating 9 items for job 1",
139             "Frobnicating 2 items for job 3",
140             );
141              
142             Outputs items that can be updated later, as long as no intervening output
143             (like from C, C or C) has happened. If you want to output
144             lines that should not be overwritten later, see C<output_permanent>>
145              
146             =cut
147              
148 8     8 1 90 sub output_list( $self, @items ) {
  8         11  
  8         16  
  8         10  
149 8 50       124 if( $self->interactive ) {
150 0           $self->output_permanent(@items);
151             #sleep 1;
152 0           $self->_last_lines( 0+@items);
153             }
154             }
155              
156             =head2 C<< ->fresh_output >>
157              
158             $o->fresh_output();
159              
160             Helper subroutine to make all items from the last output list remain as is.
161              
162             For compatibility between output to a terminal and output without a terminal,
163             you should use C<< ->output_permanent >> for things that should be permanent
164             instead.
165              
166             =cut
167              
168 0     0 1   sub fresh_output( $self ) {
  0            
  0            
169 0           $self->_last_lines( 0 );
170             }
171              
172             1;