File Coverage

blib/lib/Zoidberg/Utils/Output.pm
Criterion Covered Total %
statement 49 146 33.5
branch 15 64 23.4
condition 8 32 25.0
subroutine 11 18 61.1
pod 6 8 75.0
total 89 268 33.2


line stmt bran cond sub pod time code
1              
2             package Zoidberg::Utils::Output;
3              
4             our $VERSION = '0.981';
5              
6 22     22   138 use strict;
  22         47  
  22         887  
7 22     22   3364 use Data::Dumper;
  22         23281  
  22         1660  
8 22     22   3161 use POSIX qw/floor ceil/;
  22         25741  
  22         233  
9             use Exporter::Tidy
10 22         245 default => [qw/output message debug complain/],
11 22     22   5702 other => [qw/typed_output output_is_captured/];
  22         31  
12              
13             our %colours = ( # Copied from Term::ANSIScreen
14             'clear' => 0, 'reset' => 0,
15             'bold' => 1, 'dark' => 2,
16             'underline' => 4, 'underscore' => 4,
17             'blink' => 5, 'reverse' => 7,
18             'concealed' => 8,
19              
20             'black' => 30, 'on_black' => 40,
21             'red' => 31, 'on_red' => 41,
22             'green' => 32, 'on_green' => 42,
23             'yellow' => 33, 'on_yellow' => 43,
24             'blue' => 34, 'on_blue' => 44,
25             'magenta' => 35, 'on_magenta' => 45,
26             'cyan' => 36, 'on_cyan' => 46,
27             'white' => 37, 'on_white' => 47,
28             );
29              
30             sub output_is_captured {
31 0 0   0 1 0 return $Zoidberg::CURRENT->{_builtin_output} ? 1 : 0;
32             }
33              
34             sub output {
35 0 0   0 1 0 if ($Zoidberg::CURRENT->{_builtin_output}) { # capturing output from builtin
36 0         0 push @{ $Zoidberg::CURRENT->{_builtin_output} }, @_;
  0         0  
37 0         0 return 1;
38             }
39 0         0 else { typed_output('output', @_) }
40             }
41              
42             sub message {
43 0 0   0 1 0 return 1 if ! $Zoidberg::CURRENT->{settings}{interactive};
44 0         0 typed_output('message', @_);
45             }
46              
47             sub debug {
48 7985     7985 1 27478 my $class = caller;
49 22     22   7447 no strict 'refs';
  22         29  
  22         1395781  
50             #local $Data::Dumper::Maxdepth = 2;
51 7985 50 33     63469 return 1 unless $Zoidberg::CURRENT->{settings}{debug} || ${$class.'::DEBUG'};
  7985         69796  
52 0         0 my $fh = select STDERR;
53 0         0 my @caller = caller;
54 0         0 typed_output('debug', "$caller[0]: $caller[2]: ", @_);
55 0         0 select $fh;
56 0         0 1;
57             }
58              
59             sub complain { # strip @INC: for little less verbose output
60 10 50 33 10 1 118 return 0 unless @_ || $@;
61 10 50       46 my @error = @_ ? (@_) : ($@);
62 10         112 my $fh = select STDERR;
63 10         26 typed_output('error', map {s/\(\@INC contains\: (.*?)\)\s*//g; $_} @error);
  10         36  
  10         52  
64 10         80 select $fh;
65 10         68 1;
66             }
67              
68             sub typed_output {
69 10     10 1 44 my $type = shift;
70 10         30 my @dinge = @_;
71 10 50       32 return unless @dinge > 0;
72              
73 10   33     64 $type = $Zoidberg::CURRENT->{settings}{output}{$type} || $type;
74 10 50       48 return 1 if $type eq 'mute';
75              
76 10         10 my $coloured;
77 10 50 0     118 print "\e[$colours{$type}m" and $coloured = 1
      33        
      33        
78             if exists $colours{$type}
79             and $Zoidberg::CURRENT->{settings}{interactive} and $ENV{CLICOLOR};
80              
81 10 50       42 $dinge[-1] .= "\n" unless ref $dinge[-1];
82 10         20 for (@dinge) {
83 10 50       48 $_ = $_->scalar() if ref($_) eq 'Zoidberg::Utils::Output::Scalar';
84 10 50 33     92 unless (ref $_) { print $_ }
  0 50       0  
  0 50       0  
    0          
85 0         0 elsif (ref($_) eq 'ARRAY' and ! grep { ref($_) } @$_) { output_list(@$_) }
86             elsif (ref($_) eq 'Zoidberg::Utils::Error') {
87 10 50       36 if ($$_{debug}) { print map {s/^\$VAR1 = //; $_} Dumper $_ }
  0         0  
  0         0  
  0         0  
88             else {
89 10 50 33     68 next if $$_{silent} || $$_{printed}++;
90 0         0 print $_->stringify(format => 'gnu');
91             }
92             }
93             elsif (ref($_) =~ /Zoidberg/) {
94 0         0 complain 'Cowardly refusing to dump object of class '.ref($_);
95             }
96 0         0 else { print map {s/^\$VAR1 = //; $_} Dumper $_ }
  0         0  
  0         0  
97             }
98              
99 10 50       36 print "\e[$colours{reset}m" if $coloured;
100            
101 10         16 1;
102             }
103              
104             sub output_list { # takes minimum number of rows, but fills cols first
105 0     0 0 0 my (@items) = @_;
106 0         0 my $width = $ENV{COLUMNS};
107              
108 0 0       0 return print join("\n", @items), "\n" unless $Zoidberg::CURRENT->{settings}{interactive};
109              
110 0         0 my $len = 0;
111 0   0     0 $_ > $len and $len = $_ for map {s/\t/ /g; length $_} @items;
  0         0  
  0         0  
112 0         0 $len += 2; # spacing
113 0 0       0 return print join("\n", @items), "\n" if $width < (2 * $len); # rows == items
114 0 0       0 return print join(' ', @items), "\n" if $width > (@items * $len); # 1 row
115              
116 0         0 my $cols = int($width / $len ) - 1; # 0 based
117 0         0 my $rows = int(@items / ($cols+1)); # 0 based ceil
118 0 0       0 $rows -= 1 unless @items % ($cols+1); # tune ceil
119 0         0 my @rows;
120 0         0 for my $r (0 .. $rows) {
121 0         0 my @row = map { $items[ ($_ * ($rows+1)) + $r] } 0 .. $cols;
  0         0  
122 0         0 push @rows, join '', map { $_ .= ' 'x($len - length $_) } @row;
  0         0  
123             }
124             #print STDERR scalar(@items)." items, $len long, $width width, $cols+1 cols, $rows+1 rows\n";
125 0         0 print join("\n", @rows), "\n";
126             }
127              
128             sub output_sql { # kan vast schoner
129 0 0   0 0 0 shift unless ref($_[0]) eq 'ARRAY';
130 0         0 my $width = $ENV{COLUMNS};
131 0 0 0     0 if (! $Zoidberg::CURRENT->{settings}{interactive} || !defined $width) {
132 0         0 return (print join("\n", map {join(', ', @{$_})} @_)."\n");
  0         0  
  0         0  
133             }
134 0         0 my @records = @_;
135 0         0 my @longest = ();
136 0         0 @records = map {[map {s/\'/\\\'/g; "'".$_."'"} @{$_}]} @records; # escape quotes + safety quotes
  0         0  
  0         0  
  0         0  
  0         0  
137 0         0 foreach my $i (0..$#{$records[0]}) {
  0         0  
138 0 0       0 map {if (length($_) > $longest[$i]) {$longest[$i] = length($_);} } map {$_->[$i]} @records;
  0         0  
  0         0  
  0         0  
139             }
140             #print "debug: records: ".Dumper(\@records)." longest: ".Dumper(\@longest);
141 0         0 my $record_length = 0; # '[' + ']' - ', '
142 0         0 for (@longest) { $record_length += $_ + 2; } # length (', ') = 2
  0         0  
143 0 0       0 if ($record_length <= $width) { # it fits ! => horizontal lay-out
144 0         0 my $cols = floor($width / ($record_length+2)); # we want two spaces to saperate coloms
145 0         0 my @strings = ();
146 0         0 for (@records) {
147 0         0 my @record = @{$_};
  0         0  
148 0         0 for (0..$#record-1) { $record[$_] .= ', '.(' 'x($longest[$_] - length($record[$_]))); }
  0         0  
149 0         0 $record[$#record] .= (' 'x($longest[$#record] - length($record[$#record])));
150 0 0       0 if ($cols > 1) { push @strings, "[".join('', @record)."]"; }
  0         0  
151 0         0 else { print "[".join('', @record)."]\n"; }
152             }
153 0 0       0 if ($cols > 1) {
154 0         0 my $rows = ceil(($#strings+1) / $cols);
155 0         0 foreach my $i (0..$rows-1) {
156 0         0 for (0..$cols) { print $strings[$_*$rows+$i]." "; }
  0         0  
157 0         0 print "\n";
158             }
159             }
160             }
161 0         0 else { for (@records) { print "[\n ".join(",\n ", @{$_})."\n]\n"; } } # vertical lay-out
  0         0  
  0         0  
162 0         0 return 1;
163             }
164              
165             package Zoidberg::Utils::Output::Scalar;
166              
167             our $VERSION = '0.981';
168              
169             use overload
170 22         438 '""' => \&scalar,
171             'bool' => \&error,
172             '@{}' => \&array,
173 22     22   209 fallback => 'TRUE';
  22         68  
174              
175 168     168   5887 sub new { bless \[@_[1,2,3]], $_[0] }
176              
177 0     0   0 sub error { my $s = ${ shift() }; $$s[0] }
  0         0  
  0         0  
178              
179             sub scalar {
180 6     6   415 my $s = ${ shift() };
  6         75  
181 6 50 33     108 $$s[1] = join "\n", @{$$s[2]} if ! defined $$s[1] and $$s[2];
  0         0  
182 6         628 return $$s[1];
183             }
184              
185             sub array {
186 0     0     my $s = ${ shift() };
  0            
187 0 0         if (! defined $$s[2]) {
188 0 0         $$s[2] = (ref($$s[1]) eq 'ARRAY') ? $$s[1] :
    0          
189             ref($$s[1]) ? [$$s[1]] : [ split /\n/, $$s[1] ];
190             }
191 0           return $$s[2];
192             }
193              
194              
195             1;
196              
197             __END__