File Coverage

blib/lib/Table/Simple/Output.pm
Criterion Covered Total %
statement 84 94 89.3
branch 3 6 50.0
condition n/a
subroutine 15 16 93.7
pod 8 9 88.8
total 110 125 88.0


line stmt bran cond sub pod time code
1             package Table::Simple::Output;
2              
3 2     2   1096 use Moose;
  2         4  
  2         13  
4 2     2   13320 use Moose::Util::TypeConstraints;
  2         6  
  2         18  
5 2     2   4377 use namespace::autoclean;
  2         4  
  2         18  
6              
7 2     2   142 use Carp qw(carp);
  2         4  
  2         2377  
8              
9             =head1 NAME
10              
11             Table::Simple::Output - generates ASCII output for an Table::Simple object
12              
13             =head1 DESCRIPTION
14              
15             This class generates the ASCII table output for a L<Table::Simple> object.
16             The output functionality was split to make subclassing easier.
17              
18             =head2 ATTRIBUTES
19              
20             =over 4
21              
22             =item column_marker
23              
24             This attribute is the character to mark the beginning or end of a column. The
25             default is ":"
26              
27             =back
28              
29             =cut
30              
31             has 'column_marker' => (
32             is => 'ro',
33             isa => 'Str',
34             default => ":",
35             );
36              
37             =over 4
38              
39             =item horizontal_rule
40              
41             This attribute is the character to mark horizontal lines in the table. The
42             default is "="
43              
44             =back
45              
46             =cut
47              
48             has 'horizontal_rule' => (
49             is => 'ro',
50             isa => 'Str',
51             default => '=',
52             );
53              
54             =over 4
55              
56             =item intersection_marker
57              
58             This attribute is the character marking the intersection between the column
59             marker and a horizontal rule. The default is "+"
60              
61             =back
62              
63             =cut
64              
65             has 'intersection_marker' => (
66             is => 'ro',
67             isa => 'Str',
68             default => "+",
69             );
70              
71             =over 4
72              
73             =item padding
74              
75             This attribute defines the amount of spaces to put around data rows. The
76             default is 1 space.
77              
78             =back
79              
80             =cut
81              
82             has 'padding' => (
83             is => 'ro',
84             isa => 'Int',
85             default => 1,
86             );
87              
88             =over 4
89              
90             =item table
91              
92             This attribute is required at construction time. It is the table to be
93             output. It must be an object of type L<Table::Simple>.
94              
95             =back
96              
97             =cut
98              
99             has 'table' => (
100             is => 'ro',
101             isa => 'Table::Simple',
102             required => 1,
103             );
104              
105             has '_widths' => (
106             is => 'ro',
107             isa => 'HashRef[Int]',
108             traits => [ 'Hash' ],
109             default => sub { {} },
110             handles => {
111             '_set_width' => 'set',
112             '_get_width' => 'get',
113             },
114             lazy => 1,
115             );
116              
117             has '_hrule' => (
118             is => 'rw',
119             isa => 'Str',
120             lazy_build => 1,
121             );
122              
123             has '_blank_row' => (
124             is => 'rw',
125             isa => 'Str',
126             lazy_build => 1,
127             );
128              
129             sub BUILD {
130 2     2 0 5 my $self = shift;
131              
132 2 50       70 $self->_compute_widths if defined $self->table;
133             }
134              
135              
136             sub _compute_widths {
137 2     2   7 my $self = shift;
138 2         55 my $table = $self->table;
139            
140 2         57 my $total = $table->columns->Length - 1;
141              
142 2         16 foreach my $column ( $table->get_columns ) {
143 4         133 $self->_set_width( $column->name =>
144             ( $column->width + ( 2 * $self->padding ) ) );
145 4         116 $total += $column->width + ( 2 * $self->padding );
146             }
147              
148 2         74 $self->_set_width( '_total' => $total );
149              
150             }
151              
152             sub _build__hrule {
153 2     2   4 my $self = shift;
154 2         59 my $table = $self->table;
155              
156 2         61 my $hrule = $self->intersection_marker;
157 2         8 foreach my $column ( $table->get_columns ) {
158 4         161 $hrule .= $self->horizontal_rule x $self->_get_width($column->name());
159 4         113 $hrule .= $self->intersection_marker;
160             }
161 2         5 $hrule .= "\n";
162              
163 2         52 return $hrule;
164             }
165              
166             sub _build__blank_row {
167 0     0   0 my $self = shift;
168 0         0 my $table = $self->table;
169              
170 0         0 my $blank_row = $self->column_marker;
171 0         0 foreach my $column ( $table->get_columns ) {
172 0         0 $blank_row .= " " x $self->_get_width($column->name());
173 0         0 $blank_row .= $self->column_marker;
174             }
175 0         0 $blank_row .= "\n";
176              
177 0         0 return $blank_row;
178             }
179              
180             =head2 METHODS
181              
182             =over 4
183              
184             =item center($text, $width)
185              
186             This method takes a text string and a width and centers the text in the
187             width given. It returns the text string padded with spaces to put the
188             text in the middle of the width.
189              
190             =back
191              
192             =cut
193              
194             sub center {
195 6     6 1 19 my $self = shift;
196 6         12 my $text = shift;
197 6         8 my $width = shift;
198              
199 6         19 my $padding = int ( ( $width - length($text) ) / 2 );
200 6         17 my $left = " " x $padding . $text;
201 6         13 my $right = " " x ($width - length($left));
202 6         15 return $left . $right;
203              
204             }
205              
206             =over 4
207              
208             =item left_justify($text, $width)
209              
210             This puts text against the left margin of a table cell, padded with
211             spaces until it is the specified width.
212              
213             =back
214              
215             =cut
216              
217             sub left_justify {
218 4     4 1 6 my $self = shift;
219 4         8 my $text = shift;
220 4         6 my $width = shift;
221              
222 4         25 return " " . $text . " " x ($width - ( length($text) + 1 ));
223             }
224              
225             =over 4
226              
227             =item right_justify($text, $width)
228              
229             This method puts text against the right margin of a table cell, padded
230             with spaces until it is the specified width.
231              
232             =back
233              
234             =cut
235              
236             sub right_justify {
237 4     4 1 7 my $self = shift;
238 4         7 my $text = shift;
239 4         7 my $width = shift;
240              
241 4         15 return " " x ( $width - ( length($text) + 1 )) . $text . " ";
242             }
243              
244             =over 4
245              
246             =item build_row_output( @array )
247              
248             This method returns a scalar string composed of the rows specified in
249             the input @array.
250              
251             =back
252              
253             =cut
254              
255             sub build_row_output {
256 2     2 1 12 my $self = shift;
257 2         55 my $table = $self->table;
258              
259 2         4 my $rv;
260 2         6 foreach my $row ( @_ ) {
261 4 50       95 if ( $row > $table->row_count ) {
262 0         0 carp "$row does not exist in the given table.";
263 0         0 next;
264             }
265 4         108 $rv .= $self->column_marker;
266 4         15 foreach my $column ( $table->get_columns ) {
267 8         269 my $format = $column->output_format;
268 8         256 $rv .= $self->$format(
269             $column->get_row($row),
270             $self->_get_width( $column->name ) );
271 8         226 $rv .= $self->column_marker;
272             }
273 4         8 $rv .= "\n";
274 4         103 $rv .= $self->_hrule;
275             }
276              
277 2         7 return $rv;
278             }
279              
280             =over 4
281              
282             =item build_column_name_output
283              
284             This method returns a string scalar composed of column names centered in
285             the width for each column.
286              
287             =back
288              
289             =cut
290              
291             sub build_column_name_output {
292 2     2 1 6 my $self = shift;
293              
294 2         50 my $table = $self->table;
295            
296 2         52 my $rv .= $self->_hrule;
297 2         56 $rv .= $self->column_marker;
298 2         17 foreach my $column ( $table->get_columns ) {
299 4         129 $rv .= $self->center( $column->name,
300             $self->_get_width( $column->name ) );
301 4         113 $rv .= $self->column_marker;
302             }
303 2         6 $rv .= "\n";
304 2         73 $rv .= $self->_hrule;
305              
306 2         7 return $rv;
307             }
308              
309             =over 4
310              
311             =item build_table_name_output
312              
313             This outputs the L<Table::Simple> name attribute centered in its own row. It
314             returns a string scalar.
315              
316             =back
317              
318             =cut
319              
320             sub build_table_name_output {
321 2     2 1 5 my $self = shift;
322              
323 2         82 my $table_width = $self->_get_width('_total');
324              
325 2         3 my $rv;
326              
327 2         68 $rv .= $self->_hrule;
328 2         69 $rv .= $self->column_marker;
329 2         66 $rv .= $self->center($self->table->name, $table_width);
330 2         62 $rv .= $self->column_marker;
331 2         5 $rv .= "\n";
332              
333 2         7 return $rv;
334              
335             }
336              
337             =over 4
338              
339             =item build_table_output
340              
341             This method returns a string scalar composed of the table name row (if
342             defined), column names, and all row values.
343              
344             =back
345              
346             =cut
347              
348             sub build_table_output {
349 2     2 1 4 my $self = shift;
350              
351 2         32 my $rv;
352              
353 2 50       64 $rv .= $self->build_table_name_output if defined $self->table->name;
354 2         12 $rv .= $self->build_column_name_output;
355 2         55 $rv .= $self->build_row_output( 0..( $self->table->row_count - 1 ) );
356              
357 2         151 return $rv;
358             }
359              
360             =over 4
361              
362             =item print_table
363              
364             This method outputs the string scalar from the build_table_output() method
365             to standard out.
366              
367             =back
368              
369             =cut
370              
371             sub print_table {
372 2     2 1 15 my $self = shift;
373              
374 2         9 print $self->build_table_output;
375             }
376              
377             =head1 LICENSE
378              
379             Copyright (C) 2010 Mark Allen
380              
381             This program is free software; you can redistribute it and/or modify it
382             under the terms of either: the GNU General Public License as published
383             by the Free Software Foundation; or the Artistic License.
384              
385             See http://dev.perl.org/licenses/ for more information.
386              
387             =head1 AUTHOR
388              
389             Mark Allen <mrallen1@yahoo.com>
390              
391             =head1 SEE ALSO
392              
393             L<Moose>, L<Table::Simple>, L<Table::Simple::Output::Theory>
394              
395             =cut
396              
397             __PACKAGE__->meta->make_immutable();
398             1;