File Coverage

lib/Text/ASCIITable/EasyTable.pm
Criterion Covered Total %
statement 80 106 75.4
branch 18 32 56.2
condition 8 13 61.5
subroutine 14 16 87.5
pod 1 5 20.0
total 121 172 70.3


line stmt bran cond sub pod time code
1             package Text::ASCIITable::EasyTable;
2              
3 1     1   708 use strict;
  1         3  
  1         28  
4 1     1   5 use warnings;
  1         2  
  1         24  
5              
6 1     1   573 use Data::Dumper;
  1         6807  
  1         63  
7 1     1   670 use JSON;
  1         8149  
  1         5  
8 1     1   142 use List::Util qw(pairs);
  1         2  
  1         98  
9 1     1   7 use Scalar::Util qw(reftype);
  1         1  
  1         43  
10 1     1   572 use Text::ASCIITable;
  1         7142  
  1         53  
11              
12 1     1   7 use parent qw(Exporter);
  1         2  
  1         7  
13              
14             our @EXPORT = qw(easy_table); ## no critic (ProhibitAutomaticExportation)
15              
16             our $VERSION = '1.003';
17              
18             ########################################################################
19             {
20             ## no critic (RequireArgUnpacking)
21              
22 8     8 0 14 sub is_array { push @_, 'ARRAY'; goto &_is_type; }
  8         19  
23 5     5 0 8 sub is_hash { push @_, 'HASH'; goto &_is_type; }
  5         12  
24 13   33 13   75 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 5     5 1 27536 my (%options) = @_;
54              
55             die "'data' must be ARRAY\n"
56 5 50       13 if !is_array $options{data};
57              
58 5         7 my @columns;
59              
60 5 50       16 if ( $options{columns} ) {
    100          
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       7 if !is_array $options{rows};
69              
70             die "'rows' must be key/value pairs\n"
71 3 50       6 if @{ $options{rows} } % 2;
  3         9  
72              
73 3         4 @columns = map { $_->[0] } pairs @{ $options{rows} };
  6         20  
  3         37  
74             }
75             else {
76 2         3 @columns = keys %{ $options{data}->[0] };
  2         5  
77             }
78              
79 5         17 $options{columns} = \@columns;
80              
81 5         14 my $data = _render_data( %options, columns => \@columns, );
82              
83             return _render_table( %options, data => $data )
84 5 50       20 if !$options{json};
85              
86             # return an array of hashes
87 0         0 my @json_data;
88              
89 0         0 foreach my $row ( @{$data} ) {
  0         0  
90 0         0 my %hashed_row = map { $_ => shift @{$row} } @columns;
  0         0  
  0         0  
91 0         0 push @json_data, \%hashed_row;
92             }
93              
94 0         0 return JSON->new->pretty->encode( \@json_data );
95             }
96              
97             ########################################################################
98             sub _render_table {
99             ########################################################################
100 5     5   12 my (%options) = @_;
101              
102             # build a table...
103 5         7 my $table_options = $options{table_options};
104 5   100     31 $table_options //= {};
105              
106 5 50       11 die "'table_options' must be HASH\n"
107             if !is_hash $table_options;
108              
109 5   100     20 $table_options->{headingText} //= 'Table';
110              
111 5         31 my $t = Text::ASCIITable->new($table_options);
112              
113 5         117 my @columns = @{ $options{columns} };
  5         10  
114              
115 5 50       17 if ( $options{fix_headings} ) {
116 0         0 @columns = map { wordify $_ } @columns;
  0         0  
117             }
118              
119 5         16 $t->setCols(@columns);
120              
121 5         283 for ( @{ $options{data} } ) {
  5         9  
122 15         842 $t->addRow( @{$_} );
  15         33  
123             }
124              
125 5         389 return $t;
126             }
127              
128             ########################################################################
129             sub _render_data {
130             ########################################################################
131 5     5   16 my (%options) = @_;
132              
133             my ( $data, $rows, $columns, $sort_key )
134 5         10 = @options{qw(data rows columns sort_key)};
135              
136 5         7 my @sorted_data;
137              
138 5 50       11 if ($sort_key) {
139 0 0       0 if ( reftype($sort_key) eq 'CODE' ) {
140 0         0 @sorted_data = $sort_key->( @{$data} );
  0         0  
141             }
142             else {
143             @sorted_data
144 0         0 = sort { lc $a->{$sort_key} cmp lc $b->{$sort_key} } @{$data};
  0         0  
  0         0  
145             }
146             }
147             else {
148 5         5 @sorted_data = @{$data};
  5         8  
149             }
150              
151 5 100       10 my %row_lu = $rows ? @{$rows} : ();
  3         8  
152              
153 5         18 my @rendered_data;
154              
155 5         7 my $row_count = 0;
156              
157 5         5 for my $row ( @{$data} ) {
  5         8  
158             last
159 15 50 33     39 if defined $options{max_rows} && ++$row_count > $options{max_rows};
160              
161 15 100       24 if ($rows) {
162             push @rendered_data, [
163             map {
164             ref $row_lu{$_}
165             && reftype( $row_lu{$_} ) eq 'CODE' ? $row_lu{$_}->( $row, $_ )
166             : $row_lu{$_} ? $row->{ $row_lu{$_} }
167 18 50 66     100 : $row->{$_}
    100          
168 9         10 } @{$columns},
  9         12  
169             ];
170             }
171             else {
172 6         7 push @rendered_data, [ @{$row}{ @{$columns} } ];
  6         16  
  6         7  
173             }
174             }
175              
176 5         19 return \@rendered_data;
177             }
178              
179             1;
180              
181             ## no critic (RequirePodSections)
182              
183             __END__