File Coverage

blib/lib/Data/Tabulate.pm
Criterion Covered Total %
statement 99 99 100.0
branch 38 38 100.0
condition 27 27 100.0
subroutine 16 16 100.0
pod 10 10 100.0
total 190 190 100.0


line stmt bran cond sub pod time code
1             package Data::Tabulate;
2              
3 10     10   70221 use warnings;
  10         7978  
  10         316  
4 10     10   57 use strict;
  10         17  
  10         182  
5 9     9   39 use Carp;
  9         19  
  9         3015  
6              
7             # ABSTRACT: Table generation!
8              
9             our $VERSION = 0.09;
10              
11              
12             sub new {
13 10     10 1 2118 my ($class) = @_;
14            
15 10         31 my $self = {};
16 10         26 bless $self,$class;
17            
18 10         46 $self->max_columns(100_000);
19 10         35 $self->min_columns(1);
20            
21 10         32 return $self;
22             }
23              
24              
25             sub render {
26 11     11 1 7864 my ($self,$module,$atts) = @_;
27              
28 11 100 100     119 if ( !$self->{tabulated} and ! (
      100        
      100        
      100        
29             defined $atts and ref($atts) eq 'HASH' and
30             exists $atts->{data} and ref($atts->{data}) eq 'ARRAY'
31             ) ) {
32 4         373 croak "no data given";
33             }
34              
35 7 100       32 if ( !$module ) {
36 1         71 croak "no renderer module given";
37             }
38              
39 6 100       40 my @data = @{$atts->{data} || []};
  6         44  
40 6         22 my $tmp = $module;
41 6         46 $module = 'Data::Tabulate::Plugin::'.$module;
42            
43 6         27 $self->_load_module($module);
44            
45 5 100       28 my @table = $self->tabulate(@data) if @data;
46              
47 5 100       17 if ( !@table ) {
48 2 100       5 @table = @{ $self->{tabulated} || [] };
  2         20  
49             }
50              
51 5         21 my $plugin_obj = $module->new();
52            
53 5         25 for my $method(@{$self->{method_calls}->{$tmp}}){
  5         25  
54 2 100       18 if(!$plugin_obj->can($method->[0])){
55 1         75 croak 'renderer does not know ' . $method->[0];
56             }
57             else {
58 9     9   89 no strict 'refs';
  9         28  
  9         7911  
59 1         3 my $method_name = $method->[0];
60 1         2 my @params = @{$method->[1]};
  1         2  
61 1         5 $plugin_obj->$method_name(@params);
62             }
63            
64             }
65              
66 4 100       38 if ( !$plugin_obj->can('output') ) {
67 1         84 croak "renderer $module does not have an output method";
68             }
69              
70 3         13 return $plugin_obj->output(@table);
71             }
72              
73              
74             sub tabulate {
75 12     12 1 61 my ($self,@data) = @_;
76              
77 12         40 $self->{tabulated} = undef;
78              
79 12 100       42 return if !@data;
80            
81 11         35 my $nr = scalar @data;
82 11         44 my $cols = int sqrt $nr;
83            
84             # the calculated number of columns should not exceed the maximum
85             # number of columns that the user has specified
86 11 100       93 if($cols > $self->max_columns){
87 1         3 $cols = $self->max_columns;
88             }
89            
90             # the calculated number of columns should be greater the minimum
91             # number of columns that the user has specified
92 11 100       51 if($cols < $self->min_columns){
93 2         5 $cols = $self->min_columns;
94             }
95            
96 11         39 $self->{cols} = $cols;
97            
98 11         37 my $index = $cols - 1;
99            
100             # tabulate data
101 11         21 my @tmp_data;
102 11         34 while ( $index < $nr ) {
103 33         57 my $start = $index - $cols + 1;
104 33         90 push @tmp_data, [ @data[ $start .. $index ] ];
105 33         72 $index += $cols;
106             }
107            
108 11         27 my $fill_value = $self->{fill_value};
109              
110 11         33 my $rest = ($cols - ($nr % $cols)) % $cols;
111 11         30 $self->{rest} = $rest;
112 11 100       39 if($rest > 0){
113            
114 7         19 my $start = $nr - ($cols - $rest);
115 7         13 my $end = $nr - 1;
116            
117 7         28 push @tmp_data, [
118             @data[$start..$end],
119             ($fill_value) x $rest,
120             ];
121             }
122            
123 11         26 $self->{rows} = scalar @tmp_data;
124 11         23 $self->{tabulated} = \@tmp_data;
125            
126 11         51 return @tmp_data;
127             }
128              
129              
130             sub fill_with {
131 1     1 1 5 my ($self,$value) = @_;
132            
133 1         3 $self->{fill_value} = $value;
134             }
135              
136              
137             sub cols{
138 6     6 1 5155 my ($self) = @_;
139 6         28 return $self->{cols};
140             }
141              
142              
143             sub rows{
144 6     6 1 1198 my ($self) = @_;
145 6         26 return $self->{rows};
146             }
147              
148              
149             sub max_columns{
150 62     62 1 126 my ($self,$value) = @_;
151            
152 62 100 100     277 $self->{max_cols} = $value if defined $value and $value =~ /^[1-9]\d*$/;
153            
154 62         247 my $caller = (caller(1))[3];
155 62 100 100     341 if ( !( ($caller and $caller =~ /min_columns/) or not defined $self->min_columns) ) {
      100        
156 20 100       74 $self->min_columns($self->{max_cols}) if $self->{max_cols} < $self->min_columns;
157             }
158            
159 62         180 return $self->{max_cols};
160             }
161              
162              
163             sub min_columns{
164 82     82 1 165 my ($self,$value) = @_;
165            
166 82 100 100     263 $self->{min_cols} = $value if defined $value and $value =~ /^[1-9]\d*$/;
167            
168 82         303 my $caller = (caller(1))[3];
169 82 100 100     371 if ( !( $caller and $caller =~ /max_columns/) ){
170 31 100       95 $self->max_columns($self->{min_cols}) if $self->{min_cols} > $self->max_columns;
171             }
172            
173 82         278 return $self->{min_cols};
174             }
175              
176              
177             sub do_func{
178 2     2 1 14 my ($self,$module,$method,@params) = @_;
179            
180 2         5 push @{$self->{method_calls}->{$module}},[$method,[@params]];
  2         14  
181             }
182              
183              
184             sub reset_func{
185 1     1 1 728 my ($self,$module) = @_;
186 1         4 delete $self->{method_calls}->{$module};
187             }
188              
189              
190             #------------------------------------------------------------------------------#
191             # "private" methods #
192             #------------------------------------------------------------------------------#
193              
194             sub _load_module {
195 6     6   15 my ($self,$module) = @_;
196 6     4   431 eval "use $module";
  4         1234  
  3         23130  
  3         60  
197 6 100       123 croak "could not load $module" if $@;
198             }
199              
200             1; # End of Data::Tabulate
201              
202             __END__