File Coverage

blib/lib/Template/Plugin/ASCIITable.pm
Criterion Covered Total %
statement 131 158 82.9
branch 44 70 62.8
condition 11 23 47.8
subroutine 22 26 84.6
pod 13 14 92.8
total 221 291 75.9


line stmt bran cond sub pod time code
1             package Template::Plugin::ASCIITable;
2 1     1   172704 use base 'Template::Plugin';
  1         3  
  1         2507  
3 1     1   4531 use Text::ASCIITable;
  1         51104  
  1         81  
4 1     1   27 use vars qw($VERSION $AUTOLOAD);
  1         2  
  1         5256  
5              
6             $VERSION='0.2';
7              
8             =head1 NAME
9              
10             Template::Plugin::ASCIITable
11              
12             =head1 SYNOPSIS
13              
14             [% USE ASCIITable %]
15             blah
16             [% ASCIITable.cols('a', 'b', 'c');
17             ASCIITable.rows([1,2,3],['one','two','three']);
18             ASCIITable.draw() %]
19              
20             =head1 DESCRIPTION
21              
22             This module allows you to use L in your templates.
23              
24             A plugin object will be instantiated with the directive:
25              
26             [% USE ASCIITable %]
27              
28             You can pass a number of parameters to the constructor, for example:
29              
30             [% USE ASCIITable(cols => ['a','b','c'], show=>'rowline') %]
31              
32             See L for details.
33              
34             To obtain the table, you invoke the C method, to which you can
35             pass the same parameters:
36              
37             [% ASCIITable.draw(rows=>[[1,2,3],['one','two','three']]) %]
38              
39             =head1 METHODS
40              
41             =head2 C
42              
43             This is the plugin construtor. You should never call it directly: use
44             the C directive.
45              
46             =cut
47              
48             sub new {
49 11     11 1 144268 my ($class,$context,$params)=@_;
50 11         193 my $self=bless {hide=>{rowline=>1}},$class;
51 11 100       91 $self->handleParms(%$params) if $params;
52 11         43 return $self;
53             }
54              
55             =head2 C
56              
57             This method invokes L to obtain the textual
58             representation of the table, and returns it.
59              
60             You can pass various parameters to it, see L.
61              
62             =cut
63              
64             sub draw {
65 10     10 1 237 my ($self,@rest)=@_;
66 10 50       29 $self->handleParms(@rest) if @rest;
67 10         48 my $t=Text::ASCIITable->new({$self->_globals()});
68 10         549 $t->setCols($self->_colnames());
69 10         962 for my $c ($self->_colprops()) {
70 30 100       116 $t->alignCol($c->{name},$c->{align}) if $c->{align};
71 30 50       360 $t->alignColName($c->{name},$c->{nalign}) if $c->{nalign};
72 30 100 100     495 $t->setColWidth($c->{name},$c->{width},$c->{widen}) if ($c->{width}||-1)>0;
73             }
74 10         63 for my $r ($self->_rows()) {
75 20         4270 $t->addRow($r)
76             }
77 10         2783 my $ret=$t->draw($self->_style());
78 10         25869 my ($l,$r)=$self->_squeeze();
79 10 100       110 $ret=~s/^.{$l}//mg if $l;
80 10 100       45 $ret=~s/.{$r}$//mg if $r;
81              
82 10         127 $ret=~s/\n$//;
83 10         408 return $ret;
84             }
85              
86             my %paramSubs=(
87             hide => \&hide,
88             show => \&show,
89             cols => \&cols,
90             errors => \&errors,
91             reporterrors => \&errors,
92             allow => \&allow,
93             deny => \&deny,
94             alignheadrow => \&alignHeadRow,
95             rows => \&rows,
96             style => \&style,
97             );
98              
99             =head1 Parameters
100              
101             These parameters can be set in three ways:
102              
103             =over 4
104              
105             =item *
106              
107             passing them to the constructor
108              
109             =item *
110              
111             passing them to the C call
112              
113             =item *
114              
115             setting them with individual method calls
116              
117             =back
118              
119             All three forms are case-insensitive: you can do
120              
121             [% USE t=ASCIITable(allow=>'HTML') %]
122             [% t.Allow('html') %]
123             [% t.draw(ALLOW=>'HtMl') %]
124              
125             =cut
126              
127             sub handleParms {
128 12     12 0 36 my ($self,%params)=@_;
129 12         32 for my $k (keys %params) {
130 13 50       54 if (exists $paramSubs{lc($k)}) {
131 13         63 $paramSubs{lc($k)}->($self,$params{$k});
132             } else {
133 0         0 _die("no such parameter $k");
134             }
135             }
136 12         38 return;
137             }
138              
139             =head2 C
140              
141             This parameter accepts a list of names of features to hide. The
142             recognized names are:
143              
144             =over 4
145              
146             =item C
147              
148             The very first decoration line of the table, before the column names.
149              
150             =item C
151              
152             The line containing the names of the columns.
153              
154             =item C
155              
156             The decoration line separating the column names from the data lines.
157              
158             =item C
159              
160             The decoration line separating one data line from the next. I
161             by default>.
162              
163             =item C
164              
165             The very last decoration line, after all the data.
166              
167             =back
168              
169             Note: C will cause I
170             features to be hidden. See L.
171              
172             =cut
173              
174             sub hide {
175 4     4 1 32 my ($self,@what)=@_;
176 4 50 33     42 if (@what==1 and ref($what[0]) eq 'ARRAY') {
177 0         0 @what=@{$what[0]};
  0         0  
178             }
179 4         11 @{$self->{hide}}{grep {m{(headrow)|((head|first|last|row)line)}} map {lc $_} @what}=();
  4         14  
  4         30  
  4         16  
180 4         15 return;
181             }
182              
183             =head2 C
184              
185             This parameter does the opposite of C: sets the given features
186             to be shown.
187              
188             Note: C will cause I
189             features to be shown. See L.
190              
191             =cut
192              
193             sub show {
194 3     3 1 31 my ($self,@what)=@_;
195 3 50 33     27 if (@what==1 and ref($what[0]) eq 'ARRAY') {
196 0         0 @what=@{$what[0]};
  0         0  
197             }
198 3         7 delete @{$self->{hide}}{grep {m{(head(row|line))|((first|last|row)line)}} map {lc $_} @what};
  3         8  
  3         23  
  3         14  
199 3         14 return;
200             }
201              
202             =head2 C
203              
204             Setting this to a true value will set the C option (see
205             L).
206              
207             =cut
208              
209             sub errors {
210 0     0 1 0 my ($self,$val)=@_;
211 0         0 $self->{errors}=$val;
212 0         0 return;
213             }
214              
215             =head2 C
216              
217             This parameter accepts a list of markup names to allow inside the
218             cells. This in needed to let C calculate the correct
219             column widths. The recognized markups are:
220              
221             =over 4
222              
223             =item C
224              
225             This will allow you to use ANSI escape sequences for things like
226             colors or baldface. This usually works only if you output to a
227             compliant terminal.
228              
229             =item C
230              
231             This will allow you to use HTML tags. No check is performed on the
232             well-formedness of any such tag.
233              
234             =back
235              
236             Note: C will cause I
237             markups to be recognized. See L.
238              
239             =cut
240              
241             sub allow {
242 2     2 1 6 my ($self,@what)=@_;
243 2 50 33     18 if (@what==1 and ref($what[0]) eq 'ARRAY') {
244 0         0 @what=@{$what[0]};
  0         0  
245             }
246 2         6 @{$self->{allow}}{grep {m{ansi|html}} map {lc $_} @what}=();
  2         8  
  2         18  
  2         7  
247 2         6 return;
248             }
249              
250             =head2 C
251              
252             This parameter does the opposite of C: ignores the given
253             markups inside cells, counting them as data.
254              
255             Note: C will cause I
256             markups to be ignored. See L.
257              
258             =cut
259              
260             sub deny {
261 1     1 1 21 my ($self,@what)=@_;
262 1 50 33     10 if (@what==1 and ref($what[0]) eq 'ARRAY') {
263 0         0 @what=@{$what[0]};
  0         0  
264             }
265 1         3 delete @{$self->{allow}}{grep {m{ansi|html}} map {lc $_} @what};
  1         2  
  1         5  
  1         3  
266 1         5 return;
267             }
268              
269             =head2 C
270              
271             Sets the alignment for the column names. Can be one of:
272              
273             =over 4
274              
275             =item *
276              
277             left
278              
279             =item *
280              
281             right
282              
283             =item *
284              
285             center
286              
287             =item *
288              
289             auto
290              
291             =back
292              
293             =cut
294              
295             sub alignHeadRow {
296 0     0 1 0 my ($self,$val)=@_;
297 0         0 $self->{headrow}=$val;
298 0         0 return;
299             }
300              
301             sub _handleCols {
302 11     11   30 my ($self,@colspec)=@_;
303 11 100 100     261 if (@colspec==1 and ref($colspec[0]) eq 'ARRAY') {
304 1         2 @colspec=@{$colspec[0]};
  1         5  
305             }
306 11         24 my %colpos=();
307 11         402 my @cols=();
308 11         30 for (@colspec) {
309 30 100       58 if (ref $_) {
310 2         11 push @cols,{name=>$_->[0],
311             align=>$_->[1],
312             width=>$_->[2],
313             widen=>$_->[3],
314             nalign=>$_->[4],
315             };
316 2         86 $colpos{$_->[0]}=$#cols;
317             } else {
318 28         165 push @cols,{name=>$_};
319 28         84 $colpos{$_}=$#cols;
320             }
321             }
322 11         141 return (\@cols,\%colpos)
323             }
324              
325             =head2 C
326              
327             This parameter sets the names, and optionally some properties, of all
328             the columns in the table. To add columns to an existing table, use
329             the L parameter (usually as a method).
330              
331             This parameter accepts a list of column specifications. Each
332             specification can be:
333              
334             =over 4
335              
336             =item a single string
337              
338             that becomes the name of the column, and width and alignment default
339             to 'auto'
340              
341             =item an array reference
342              
343             that contains, in order:
344              
345             =over 8
346              
347             =item *
348              
349             the name
350              
351             =item *
352              
353             the alignment for the data, one of 'left', 'right', 'center', 'auto' (see
354             L)
355              
356             =item *
357              
358             the maximum width of the column, in characters (see
359             L)
360              
361             =item *
362              
363             whether to force the width of the column, a boolean (see
364             L, the last parameter)
365              
366             =item *
367              
368             the name alignment (see L)
369              
370             =back
371              
372             =back
373              
374             Note: this sets I. C
375             will result in a table with I column. See L.
376              
377             =cut
378              
379             sub cols {
380 10     10 1 402 my $self=shift;
381 10         114 ($self->{cols},$self->{colpos})=$self->_handleCols(@_);
382 10         51 return;
383             }
384              
385             =head2 C
386              
387             This parameter works like C, but adds the given columns to the
388             existing ones, instead of replacing them. So
389             C will result in a table with 3 columns.
390              
391             =cut
392              
393             sub addCols {
394 1     1 1 28 my $self=shift;
395 1         4 my ($cols,$colpos)=$self->_handleCols(@_);
396 1         2 push @{$self->{cols}},@$cols;
  1         4  
397 1         4 @{$self->{colpos}}{keys %$colpos}=values %$colpos;
  1         4  
398 1         7 return;
399             }
400              
401             =head2 C
402              
403             This parameter accepts a list of array references, one per row. Each
404             row must have one scalar element per each column that will be
405             produced.
406              
407             Note that, because of the way this plugin works, you can do something
408             like:
409              
410             [% USE t=ASCIITable(cols=>['a','b']);
411             t.rows([1,2,3],[4,5,6]);
412             t.addCols('c');
413             t.draw() %]
414              
415             And it will print a 3x2 table.
416              
417             Note: this sets I.
418             C
419             will result in a table with I row. See L.
420              
421             =cut
422              
423             sub rows {
424 9     9 1 359 my ($self,@rows)=@_;
425 9 50 33     201 if (@rows==1 and ref($rows[0]) eq 'ARRAY') {
426 0         0 @rows=@{$rows[0]};
  0         0  
427             }
428 9         32 $self->{rows}=[@rows];
429 9         47 return;
430             }
431              
432             =head2 C
433              
434             This parameter works like C, but adds the given rows to the
435             existing ones, instead of replacing them. So
436             C
437             will result in a table with 3 rows.
438              
439             =cut
440              
441             sub addRows {
442 2     2 1 51 my ($self,@row)=@_;
443 2 50 33     16 if (@row==1 and ref($row[0]) eq 'ARRAY') {
444 2         4 @row=@{$row[0]};
  2         7  
445             }
446 2         3 push @{$self->{rows}},[@row];
  2         7  
447 2         10 return;
448             }
449              
450             my %styles=(
451             'default'=>
452             {lines=>undef,
453             globals=>{hide=>'rowline'},
454             },
455             'rest-simple'=>
456             {lines=>[
457             ['<','>','=',' '],
458             ['<','>',' '],
459             ['<','>','=',' '],
460             ['<','>',' '],
461             ['<','>','=',' '],
462             ['<','>','-',' '],
463             1,1,
464             ],
465             globals=>{hide=>'rowline'},
466             },
467             'rest-grid'=>
468             {lines=>[
469             ['+','+','-','+'],
470             ['|','|','|'],
471             ['+','+','=','+'],
472             ['|','|','|'],
473             ['+','+','-','+'],
474             ['+','+','-','+'],
475             0,0,
476             ],
477             globals=>{show=>'rowline'},
478             },
479             );
480              
481             =head2 C