File Coverage

lib/Text/ASCIITable/EasyTable.pm
Criterion Covered Total %
statement 89 123 72.3
branch 23 38 60.5
condition 9 16 56.2
subroutine 14 17 82.3
pod 1 5 20.0
total 136 199 68.3


line stmt bran cond sub pod time code
1             package Text::ASCIITable::EasyTable;
2              
3 1     1   737 use strict;
  1         2  
  1         28  
4 1     1   4 use warnings;
  1         2  
  1         23  
5              
6 1     1   585 use Data::Dumper;
  1         6848  
  1         62  
7 1     1   659 use JSON;
  1         8290  
  1         6  
8 1     1   145 use List::Util qw(pairs);
  1         2  
  1         84  
9 1     1   7 use Scalar::Util qw(reftype);
  1         2  
  1         46  
10 1     1   598 use Text::ASCIITable;
  1         7651  
  1         54  
11              
12 1     1   7 use parent qw(Exporter);
  1         2  
  1         8  
13              
14             our @EXPORT = qw(easy_table); ## no critic (ProhibitAutomaticExportation)
15              
16             our $VERSION = '1.005';
17              
18             ########################################################################
19             {
20             ## no critic (RequireArgUnpacking)
21              
22 9     9 0 17 sub is_array { push @_, 'ARRAY'; goto &_is_type; }
  9         26  
23 6     6 0 10 sub is_hash { push @_, 'HASH'; goto &_is_type; }
  6         18  
24 15   33 15   102 sub _is_type { return ref $_[0] && reftype( $_[0] ) eq $_[1]; }
25             }
26             ########################################################################
27              
28             ########################################################################
29             sub uncamel {
30             ########################################################################
31 0     0 0 0 my ($str) = @_;
32              
33 0         0 while ( $str =~ s/^(.)(.*?)([[:upper:]])/\l$1$2_\l$3/xsmg ) { }
34              
35 0         0 return $str;
36             }
37              
38             ########################################################################
39             sub wordify {
40             ########################################################################
41 0     0 0 0 my ($str) = @_;
42              
43 0         0 $str = uncamel($str);
44              
45 0         0 $str =~ s/_(.)/ \u$1/xsmg;
46              
47 0         0 return ucfirst $str;
48             }
49              
50             ########################################################################
51             sub easy_table {
52             ########################################################################
53 6     6 1 34896 my (%options) = @_;
54              
55             die "'data' must be ARRAY\n"
56 6 50       18 if !is_array $options{data};
57              
58 6         13 my @columns;
59              
60 6 50 33     29 if ( $options{columns} && !$options{index} ) {
    100          
    50          
61             die "'columns' must be an ARRAY\n"
62 0 0       0 if !is_array $options{columns};
63              
64 0         0 @columns = @{ $options{columns} };
  0         0  
65             }
66             elsif ( $options{rows} ) {
67             die "'rows' must be ARRAY\n"
68 3 50       8 if !is_array $options{rows};
69              
70             die "'rows' must be key/value pairs\n"
71 3 50       5 if @{ $options{rows} } % 2;
  3         11  
72              
73 3         6 @columns = map { $_->[0] } pairs @{ $options{rows} };
  6         22  
  3         24  
74             }
75             elsif ( $options{index} ) {
76              
77 0         0 @columns = map { $_->[0] } pairs @{ $options{index} };
  0         0  
  0         0  
78              
79 0         0 my %index = @{ $options{index} };
  0         0  
80              
81             $options{rows} = [
82             map {
83 0     0   0 ( $_ => sub { return shift->{ $index{ shift() } } } )
  0         0  
84 0         0 } @columns
85             ];
86             }
87             else {
88 3         4 @columns = keys %{ $options{data}->[0] };
  3         11  
89             }
90              
91 6         20 $options{columns} = \@columns;
92              
93 6         21 my $data = _render_data( %options, columns => \@columns, );
94              
95             return _render_table( %options, data => $data )
96 6 50       29 if !$options{json};
97              
98             # return an array of hashes
99 0         0 my @json_data;
100              
101 0         0 foreach my $row ( @{$data} ) {
  0         0  
102 0         0 my %hashed_row = map { $_ => shift @{$row} } @columns;
  0         0  
  0         0  
103 0         0 push @json_data, \%hashed_row;
104             }
105              
106 0         0 return JSON->new->pretty->encode( \@json_data );
107             }
108              
109             ########################################################################
110             sub _render_table {
111             ########################################################################
112 6     6   20 my (%options) = @_;
113              
114             # build a table...
115 6         11 my $table_options = $options{table_options};
116 6   100     24 $table_options //= {};
117              
118 6 50       13 die "'table_options' must be HASH\n"
119             if !is_hash $table_options;
120              
121 6   100     27 $table_options->{headingText} //= 'Table';
122              
123 6         35 my $t = Text::ASCIITable->new($table_options);
124              
125 6         162 my @columns = @{ $options{columns} };
  6         16  
126              
127 6 50       15 if ( $options{fix_headings} ) {
128 0         0 @columns = map { wordify $_ } @columns;
  0         0  
129             }
130              
131 6         19 $t->setCols(@columns);
132              
133 6         357 for ( @{ $options{data} } ) {
  6         15  
134              
135 21 100       1245 if ( !@{$_} ) {
  21         43  
136 1         6 $t->addRowLine;
137 1         17 next;
138             }
139              
140 20         25 $t->addRow( @{$_} );
  20         47  
141             }
142              
143 6         474 return $t;
144             }
145              
146             ########################################################################
147             sub _render_data {
148             ########################################################################
149 6     6   18 my (%options) = @_;
150              
151             my ( $data, $rows, $columns, $sort_key )
152 6         28 = @options{qw(data rows columns sort_key)};
153              
154 6         12 my @sorted_data;
155              
156 6 50       11 if ($sort_key) {
157 0 0       0 if ( reftype($sort_key) eq 'CODE' ) {
158 0         0 @sorted_data = $sort_key->( @{$data} );
  0         0  
159             }
160             else {
161             @sorted_data
162 0         0 = sort { lc $a->{$sort_key} cmp lc $b->{$sort_key} } @{$data};
  0         0  
  0         0  
163             }
164             }
165             else {
166 6         7 @sorted_data = @{$data};
  6         15  
167             }
168              
169 6 100       12 my %row_lu = $rows ? @{$rows} : ();
  3         10  
170              
171 6         25 my @rendered_data;
172              
173 6         10 my $row_count = 0;
174              
175 6         8 for my $row ( @{$data} ) {
  6         10  
176              
177 21         37 print {*STDERR} Dumper( [ row => $row ] );
  21         97  
178              
179 21 100       1961 if ( !$row ) {
180 1         5 push @rendered_data, [];
181 1         3 next;
182             }
183              
184             last
185 20 50 33     59 if defined $options{max_rows} && ++$row_count > $options{max_rows};
186              
187 20 100       34 if ($rows) {
188             push @rendered_data, [
189             map {
190             ref $row_lu{$_}
191             && reftype( $row_lu{$_} ) eq 'CODE' ? $row_lu{$_}->( $row, $_ )
192             : $row_lu{$_} ? $row->{ $row_lu{$_} }
193 18 50 66     135 : $row->{$_}
    100          
194 9         12 } @{$columns},
  9         19  
195             ];
196             }
197             else {
198 11         17 push @rendered_data, [ @{$row}{ @{$columns} } ];
  11         40  
  11         16  
199             }
200             }
201              
202 6         29 return \@rendered_data;
203             }
204              
205             1;
206              
207             ## no critic (RequirePodSections)
208              
209             __END__