File Coverage

blib/lib/Map/Tube/Text/Table/Utils.pm
Criterion Covered Total %
statement 52 52 100.0
branch 8 8 100.0
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 71 71 100.0


line stmt bran cond sub pod time code
1             package Map::Tube::Text::Table::Utils;
2              
3 5     5   90348 use base qw(Exporter);
  5         23  
  5         627  
4 5     5   33 use strict;
  5         9  
  5         96  
5 5     5   22 use warnings;
  5         9  
  5         168  
6              
7 5     5   27 use List::Util qw(sum);
  5         10  
  5         632  
8 5     5   1667 use Readonly;
  5         11629  
  5         233  
9 5     5   2383 use Text::UnicodeBox;
  5         2848676  
  5         231  
10 5     5   50 use Text::UnicodeBox::Control qw(:all);
  5         10  
  5         3098  
11              
12             # Constants.
13             Readonly::Array our @EXPORT_OK => qw(table);
14             Readonly::Scalar our $EMPTY_STR => q{};
15             Readonly::Scalar our $SPACE => q{ };
16             Readonly::Scalar our $SPACE_ON_END_COUNT => 1;
17              
18             our $VERSION = 0.05;
19              
20             # Print table.
21             sub table {
22 3     3 1 7264 my ($title, $data_len_ar, $header_ar, $data_ar) = @_;
23              
24             # Check data.
25 3 100       6 if (! @{$data_ar}) {
  3         13  
26 1         5 return $EMPTY_STR;
27             }
28              
29 2         23 my $t = Text::UnicodeBox->new;
30              
31             # Table title.
32 2         2168 my $pipes_in_count = @{$data_len_ar} * 2 - 2;
  2         10  
33             $t->add_line(
34             BOX_START('bottom' => 'light', 'top' => 'light'),
35 6         24 _column_left($title, sum(map { $_ + $SPACE_ON_END_COUNT }
36 2         10 @{$data_len_ar}) + $pipes_in_count),
  2         1503  
37             BOX_END(),
38             );
39              
40             # Legend.
41 2 100       22574 if (defined $header_ar) {
42 1         6 $t->add_line(
43             BOX_START('bottom' => 'light', 'top' => 'light'),
44             _columns($header_ar, $data_len_ar),
45             );
46             }
47              
48             # Data.
49 2         8419 while (my $row_ar = shift @{$data_ar}) {
  6         26702  
50             $t->add_line(
51             BOX_START(
52 4 100       21 @{$data_ar} == 0 ? ('bottom' => 'light') : (),
  4         21  
53             ),
54             _columns($row_ar, $data_len_ar),
55             );
56             }
57              
58             # Render to output.
59 2         9 return $t->render;
60             }
61              
62             # Column text with left align.
63             sub _column_left {
64 17     17   37 my ($text, $width) = @_;
65 17         43 my $text_len = length $text;
66 17         62 return $SPACE.$text.($SPACE x ($width - $text_len));
67             }
68              
69             # Get Text::UnicodeBox columns.
70             sub _columns {
71 5     5   3636 my ($data_ar, $data_len_ar) = @_;
72 5         10 my @ret;
73 5         8 my $i = 0;
74 5         8 foreach my $item (@{$data_ar}) {
  5         14  
75 15         7346 push @ret, _column_left($item, $data_len_ar->[$i++]
76             + $SPACE_ON_END_COUNT);
77 15 100       30 if (@{$data_ar} > $i) {
  15         38  
78 10         32 push @ret, BOX_RULE;
79             } else {
80 5         15 push @ret, BOX_END;
81             }
82             }
83 5         3563 return @ret;
84             }
85              
86             1;
87              
88             __END__
89              
90             =pod
91              
92             =encoding utf8
93              
94             =head1 NAME
95              
96             Map::Tube::Text::Table::Utils - Utilities for Map::Tube::Text::Table.
97              
98             =head1 SYNOPSIS
99              
100             use Map::Tube::Text::Table::Utils qw(table);
101              
102             my $table = table($title, $data_len_ar, $header_ar, $data_ar);
103              
104             =head1 SUBROUTINES
105              
106             =over 8
107              
108             =item C<table($title, $data_len_ar, $header_ar, $data_ar)>
109              
110             Print table.
111             Returns text.
112              
113             =back
114              
115             =head1 EXAMPLE1
116              
117             use strict;
118             use warnings;
119              
120             use Encode qw(encode_utf8);
121             use Map::Tube::Text::Table::Utils qw(table);
122              
123             # Get table.
124             my $table = table('Title', [1, 2, 3], ['A', 'BB', 'CCC'], [
125             ['E', 'A', 'A'],
126             ['A', 'Ga', 'Acv'],
127             ]);
128              
129             # Print table.
130             print encode_utf8($table);
131              
132             # Output:
133             # ┌──────────────┐
134             # │ Title │
135             # ├───┬────┬─────┤
136             # │ A │ BB │ CCC │
137             # ├───┼────┼─────┤
138             # │ E │ A │ A │
139             # │ A │ Ga │ Acv │
140             # └───┴────┴─────┘
141              
142             =head1 DEPENDENCIES
143              
144             L<Exporter>,
145             L<List::Util>,
146             L<Readonly>,
147             L<Text::UnicodeBox>,
148             L<Text::UnicodeBox::Control>.
149              
150             =head1 SEE ALSO
151              
152             =over 8
153              
154             =item L<Map::Tube>
155              
156             Lightweight Routing Framework
157              
158             =item L<Map::Tube::Text::Table>
159              
160             Table output for Map::Tube
161              
162             =item L<Task::Map::Tube>
163              
164             Install the Map::Tube modules.
165              
166             =back
167              
168             =head1 REPOSITORY
169              
170             L<https://github.com/michal-josef-spacek/Map-Tube-Text-Table>
171              
172             =head1 AUTHOR
173              
174             Michal Josef Å paček L<mailto:skim@cpan.org>
175              
176             L<http://skim.cz>
177              
178             =head1 LICENSE AND COPYRIGHT
179              
180             © 2014-2020 Michal Josef Å paček
181             Artistic License
182             BSD 2-Clause License
183              
184             =head1 VERSION
185              
186             0.05
187              
188             =cut