File Coverage

blib/lib/Text/Table/Manifold.pm
Criterion Covered Total %
statement 172 240 71.6
branch 33 82 40.2
condition 7 25 28.0
subroutine 20 26 76.9
pod 8 8 100.0
total 240 381 62.9


'; "; ' . join('', @line) . ''; '; "; ' . join('', @line) . ''; '; "; ' . join('', @line) . ''; ';
line stmt bran cond sub pod time code
1             package Text::Table::Manifold;
2              
3 2     2   104726 use strict;
  2         16  
  2         55  
4 2     2   10 use warnings;
  2         4  
  2         52  
5 2     2   10 use warnings qw(FATAL utf8); # Fatalize encoding glitches.
  2         4  
  2         88  
6 2     2   918 use open qw(:std :utf8); # Undeclared streams in UTF-8.
  2         2284  
  2         11  
7              
8 2         29 use Const::Exporter constants =>
9             [
10             # Values of alignment().
11              
12             align_left => 0,
13             align_center => 1, # The default.
14             align_right => 2,
15              
16             # Values for empty(), i.e. empty string handling.
17              
18             empty_as_empty => 0, # Do nothing. The default.
19             empty_as_minus => 1,
20             empty_as_text => 2, # 'empty'.
21             empty_as_undef => 3,
22              
23             # Values for escape().
24              
25             escape_nothing => 0, # The default.
26             escape_html => 1,
27             escape_uri => 2,
28              
29             # Values for extend().
30              
31             extend_with_empty => 0, # The default.
32             extend_with_undef => 1,
33              
34             # Values for format().
35              
36             format_internal_boxed => 0, # The default.
37             format_text_csv => 1,
38             format_internal_github => 2,
39             format_internal_html => 3,
40             format_html_table => 4,
41             format_text_unicodebox_table => 5,
42              
43             # Values for include().
44              
45             include_data => 1, # Default.
46             include_footers => 2,
47             include_headers => 4, # Default.
48              
49             # Values for undef(), i.e. undef handling.
50              
51             undef_as_empty => 0,
52             undef_as_minus => 1,
53             undef_as_text => 2, # 'undef'.
54             undef_as_undef => 3, # Do nothing. The default.
55 2     2   1232 ];
  2         49428  
56              
57 2     2   4076 use HTML::Entities::Interpolate; # This module can't be loaded at runtime.
  2         14911  
  2         14  
58              
59 2     2   72 use List::AllUtils 'max';
  2         4  
  2         90  
60              
61 2     2   11 use Module::Runtime 'use_module';
  2         4  
  2         13  
62              
63 2     2   1079 use Moo;
  2         14080  
  2         15  
64              
65 2     2   3829 use Types::Standard qw/Any ArrayRef HashRef Int Str/;
  2         141123  
  2         20  
66              
67 2     2   3296 use String::TtyLength 0.02 qw/ tty_width /;
  2         44608  
  2         6191  
68              
69             has alignment =>
70             (
71             default => sub{return []},
72             is => 'rw',
73             isa => ArrayRef,
74             required => 0,
75             );
76              
77             has data =>
78             (
79             default => sub{return []},
80             is => 'rw',
81             isa => ArrayRef,
82             required => 0,
83             );
84              
85             has empty =>
86             (
87             default => sub{return empty_as_empty},
88             is => 'rw',
89             isa => Int,
90             required => 0,
91             );
92              
93             has escape =>
94             (
95             default => sub{return escape_nothing},
96             is => 'rw',
97             isa => Int,
98             required => 0,
99             );
100              
101             has extend_data =>
102             (
103             default => sub{return extend_with_empty},
104             is => 'rw',
105             isa => Int,
106             required => 0,
107             );
108              
109             has extend_footers =>
110             (
111             default => sub{return extend_with_empty},
112             is => 'rw',
113             isa => Int,
114             required => 0,
115             );
116              
117             has extend_headers =>
118             (
119             default => sub{return extend_with_empty},
120             is => 'rw',
121             isa => Int,
122             required => 0,
123             );
124              
125             has format =>
126             (
127             default => sub{return format_internal_boxed},
128             is => 'rw',
129             isa => Int,
130             required => 0,
131             );
132              
133             has footers =>
134             (
135             default => sub{return []},
136             is => 'rw',
137             isa => ArrayRef,
138             required => 0,
139             );
140              
141             has headers =>
142             (
143             default => sub{return []},
144             is => 'rw',
145             isa => ArrayRef,
146             required => 0,
147             );
148              
149             has include =>
150             (
151             default => sub{return include_data | include_headers},
152             is => 'rw',
153             isa => Int,
154             required => 0,
155             );
156              
157             has join =>
158             (
159             default => sub{return ''},
160             is => 'rw',
161             isa => Str,
162             required => 0,
163             );
164              
165             has padding =>
166             (
167             default => sub{return 0},
168             is => 'rw',
169             isa => Int,
170             required => 0,
171             );
172              
173             has pass_thru =>
174             (
175             default => sub{return {} },
176             is => 'rw',
177             isa => HashRef,
178             required => 0,
179             );
180              
181             has undef =>
182             (
183             default => sub{return undef_as_undef},
184             is => 'rw',
185             isa => Int,
186             required => 0,
187             );
188              
189             has widths =>
190             (
191             default => sub{return []},
192             is => 'rw',
193             isa => ArrayRef,
194             required => 0,
195             );
196              
197             our $VERSION = '1.01_01';
198              
199             # ------------------------------------------------
200              
201             sub _align_to_center
202             {
203 25     25   41 my($self, $s, $width, $padding) = @_;
204 25   100     58 $s ||= '';
205 25         48 my($s_width) = tty_width($s);
206 25         296 my($left) = int( ($width - $s_width) / 2);
207 25         41 my($right) = $width - $s_width - $left;
208              
209 25         74 return (' ' x ($left + $padding) ) . $s . (' ' x ($right + $padding) );
210              
211             } # End of _align_to_center;
212              
213             # ------------------------------------------------
214              
215             sub _align_to_left
216             {
217 0     0   0 my($self, $s, $width, $padding) = @_;
218 0   0     0 $s ||= '';
219 0         0 my($s_width) = tty_width($s);
220 0         0 my($right) = $width - $s_width;
221              
222 0         0 return (' ' x $padding) . $s . (' ' x ($right + $padding) );
223              
224             } # End of _align_to_left;
225              
226             # ------------------------------------------------
227              
228             sub _align_to_right
229             {
230 0     0   0 my($self, $s, $width, $padding) = @_;
231 0   0     0 $s ||= '';
232 0         0 my($s_width) = tty_width($s);
233 0         0 my($left) = $width - $s_width;
234              
235 0         0 return (' ' x ($left + $padding) ) . $s . (' ' x $padding);
236              
237             } # End of _align_to_right;
238              
239             # ------------------------------------------------
240             # Apply empty_as_* and undef_as_* options, as well as escaping option(s).
241              
242             sub _clean_data
243             {
244 3     3   8 my($self, $alignment, $headers, $data, $footers) = @_;
245 3         50 my($empty) = $self -> empty;
246 3         58 my($escape) = $self -> escape;
247 3         58 my($undef) = $self -> undef;
248              
249 3 50       21 use_module('URI::Escape') if ($escape == escape_uri);
250              
251 3         11 my($s);
252              
253 3         8 for my $row (0 .. $#$data)
254             {
255 12         19 for my $column (0 .. $#{$$data[$row]})
  12         24  
256             {
257 60         83 $s = $$data[$row][$column];
258 60 50       127 $s = defined($s)
    50          
    50          
    100          
    0          
    0          
    0          
    50          
259             ? (length($s) == 0) # tty_width() should not be necessary here.
260             ? ($empty == empty_as_minus)
261             ? '-'
262             : ($empty == empty_as_text)
263             ? 'empty'
264             : ($empty == empty_as_undef)
265             ? undef
266             : $s # No need to check to empty_as_empty here!
267             : $s
268             : ($undef == undef_as_empty)
269             ? ''
270             : ($undef == undef_as_minus)
271             ? '-'
272             : ($undef == undef_as_text)
273             ? 'undef'
274             : $s; # No need to check for undef_as_undef here!
275              
276 60 50 33     232 $s = $Entitize{$s} if (defined($s) && ($escape == escape_html) );
277 60 50       236 $s = URI::Escape::uri_escape($s) if ($escape == escape_uri); # Undef harmless here.
278 60         196 $$data[$row][$column] = $s;
279             }
280             }
281              
282             } # End of _clean_data.
283              
284             # ------------------------------------------------
285              
286             sub format_as_html_table
287             {
288 0     0 1 0 my($self, $alignment, $headers, $data, $footers) = @_;
289              
290 0         0 my($html) = use_module('HTML::Table') -> new(%{${$self -> pass_thru}{new} }, -data => $data);
  0         0  
  0         0  
291              
292 0         0 return [$html -> getTable];
293              
294             } # End of format_as_html_table.
295              
296             # ------------------------------------------------
297              
298             sub format_as_internal_boxed
299             {
300 1     1 1 4 my($self, $alignment, $headers, $data, $footers) = @_;
301 1         20 my($padding) = $self -> padding;
302 1         24 my($widths) = $self -> widths;
303 1         8 my($separator) = '+' . join('+', map{'-' x ($_ + 2 * $padding)} @$widths) . '+';
  5         17  
304 1         3 my(@output) = $separator;
305              
306 1         4 my($align);
307             my(@s);
308              
309 1         4 for my $column (0 .. $#$widths)
310             {
311 5         10 $align = $$alignment[$column];
312              
313 5 50       12 if ($align == align_left)
    50          
314             {
315 0         0 push @s, $self -> _align_to_left($$headers[$column], $$widths[$column], $padding);
316             }
317             elsif ($align == align_center)
318             {
319 5         36 push @s, $self -> _align_to_center($$headers[$column], $$widths[$column], $padding);
320             }
321             else
322             {
323 0         0 push @s, $self -> _align_to_right($$headers[$column], $$widths[$column], $padding);
324             }
325             }
326              
327 1         7 push @output, '|' . join('|', @s) . '|';
328 1         2 push @output, $separator;
329              
330 1         3 for my $row (0 .. $#$data)
331             {
332 4         8 @s = ();
333              
334 4         10 for my $column (0 .. $#$widths)
335             {
336 20         33 $align = $$alignment[$column];
337              
338 20 50       35 if ($align == align_left)
    50          
339             {
340 0         0 push @s, $self -> _align_to_left($$data[$row][$column], $$widths[$column], $padding);
341             }
342             elsif ($align == align_center)
343             {
344 20         111 push @s, $self -> _align_to_center($$data[$row][$column], $$widths[$column], $padding);
345             }
346             else
347             {
348 0         0 push @s, $self -> _align_to_right($$data[$row][$column], $$widths[$column], $padding);
349             }
350             }
351              
352 4         17 push @output, '|' . join('|', @s) . '|';
353             }
354              
355 1         2 push @output, $separator;
356              
357 1         5 return [@output];
358              
359             } # End of format_as_internal_boxed.
360              
361             # ------------------------------------------------
362              
363             sub format_as_internal_github
364             {
365 1     1 1 3 my($self, $alignment, $headers, $data, $footers) = @_;
366 1         5 my(@output) = join('|', @$headers);
367 1         43 my($widths) = $self -> widths;
368              
369 1         12 my($align);
370             my(@line);
371              
372 1         4 for my $column (0 .. $#$widths)
373             {
374 5         9 $align = $$alignment[$column];
375              
376 5 50       11 if ($align == align_left)
    50          
377             {
378 0         0 push @line, ':' . ('-' x $$widths[$column - 1]);
379             }
380             elsif ($align == align_center)
381             {
382 5         40 push @line, ':' . ('-' x $$widths[$column - 2]) . ':';
383             }
384             else
385             {
386 0         0 push @line, ('-' x $$widths[$column - 1]) . ':';
387             }
388             }
389              
390 1         5 push @output, join('|', @line);
391              
392 1         2 for my $row (0 .. $#$data)
393             {
394 4 50       6 push @output, join('|', map{defined($_) ? $_ : ''} @{$$data[$row]});
  20         41  
  4         9  
395             }
396              
397 1         5 return [@output];
398              
399             } # End of format_as_internal_github.
400              
401             # ------------------------------------------------
402              
403             sub format_as_internal_html
404             {
405 1     1 1 4 my($self, $alignment, $headers, $data, $footers) = @_;
406 1         3 my($table) = '';
407 1   50     2 my($table_options) = ${$self -> pass_thru}{new}{table} || {};
408 1         17 my(@table_keys) = sort keys %$table_options;
409 1         19 my($include) = $self -> include;
410 1         12 my(%align) =
411             (
412             0 => "
",
413             1 => "
",
414             2 => "
",
415             );
416              
417 1 50       4 if (scalar @table_keys)
418             {
419 0         0 $table .= ' ' . join(' ', map{qq|$_ = "$$table_options{$_}"|} sort keys %$table_options);
  0         0  
420             }
421              
422 1         4 my(@output) = "";
423              
424 1         3 my(@line);
425             my($value);
426              
427 1 50 33     3 if ( ($include & include_headers) && ($#$headers >= 0) )
428             {
429 1         10 push @output, '
430              
431 1         4 for my $column (0 .. $#$headers)
432             {
433 5         17 push @line, "$align{$$alignment[$column]}$$headers[$column]
434             }
435              
436 1         6 push @output, '
437 1         3 push @output, '
438             }
439              
440 1 50       4 if ($include & include_data)
441             {
442 1         21 for my $row (0 .. $#$data)
443             {
444 4         7 @line = ();
445              
446             # Every row will have the same # of columns, so we pick 1.
447              
448 4         8 for my $column (0 .. $#{$$data[0]})
  4         9  
449             {
450 20         31 $value = $$data[$row][$column];
451 20 50       28 $value = defined($value) ? $value : '';
452              
453 20         54 push @line, "$align{$$alignment[$column]}$value
454             }
455              
456 4         15 push @output, '
457             }
458             }
459              
460 1 50 33     6 if ( ($include & include_footers) && ($#$footers >= 0) )
461             {
462 0         0 push @output, '
463              
464 0         0 @line = ();
465              
466 0         0 for my $column (0 .. $#$footers)
467             {
468 0         0 push @line, "$align{$$alignment[$column]}$$footers[$column]
469             }
470              
471 0         0 push @output, '
472 0         0 push @output, '
473             }
474              
475 1         7 push @output, '
'; 476               477 1         7 return [@output]; 478               479             } # End of format_as_internal_html. 480               481             # ------------------------------------------------ 482               483             sub format_as_text_csv 484             { 485 0     0 1 0 my($self, $alignment, $headers, $data, $footers) = @_; 486               487 0   0     0 my($csv) = use_module('Text::CSV') -> new(${$self -> pass_thru}{new} || {}); 488 0         0 my($status) = $csv -> combine(@$headers); 489               490 0         0 my(@output); 491               492 0 0       0 if ($status) 493             { 494 0         0 push @output, $csv -> string; 495               496 0         0 for my $row (0 .. $#$data) 497             { 498 0         0 $status = $csv -> combine(@{$$data[$row]});   0         0   499               500 0 0       0 if ($status) 501             { 502 0         0 push @output, $csv -> string 503             } 504             else 505             { 506 0         0 die "Can't combine data:\nLine: " . $csv -> error_input . "\nMessage: " . $csv -> error_diag . "\n"; 507             } 508             } 509             } 510             else 511             { 512 0         0 die "Can't combine headers:\nHeader: " . $csv -> error_input . "\nMessage: " . $csv -> error_diag . "\n"; 513             } 514               515 0         0 return [@output]; 516               517             } # End of format_as_text_csv. 518               519             # ------------------------------------------------ 520               521             sub format_as_text_unicodebox_table 522             { 523 0     0 1 0 my($self, $alignment, $headers, $data, $footers) = @_; 524 0         0 my($include) = $self -> include; 525 0         0 my($table) = use_module('Text::UnicodeBox::Table') -> new(%{${$self -> pass_thru}{new} });   0         0     0         0   526               527 0 0 0     0 if ( ($include & include_headers) && ($#$headers >= 0) ) 528             { 529             # Note: Text::UnicodeBox::Table does not support central alignment. 530               531 0 0       0 my(@align) = map{ ($_ == align_left) ? 'left' : 'right'} @{$self -> alignment};   0         0     0         0   532               533 0         0 $table -> add_header({alignment => [@align]}, @$headers); 534             } 535               536 0 0       0 if ($include & include_data) 537             { 538 0         0 for my $row (0 .. $#$data) 539             { 540 0         0 $table -> add_row(@{$$data[$row]});   0         0   541             } 542             } 543               544 0         0 return [$table -> render]; 545               546             } # End of format_as_text_unicodebox_table. 547               548             # ------------------------------------------------ 549             # Find the maimum width of header/data/footer each column. 550               551             sub _gather_statistics 552             { 553 3     3   7 my($self, $alignment, $headers, $data, $footers) = @_; 554               555 3         12 $self -> _rectify_data($alignment, $headers, $data, $footers); 556 3         11 $self -> _clean_data($alignment, $headers, $data, $footers); 557               558 3         10 my(@column); 559             my($header_width); 560 3         0 my(@max_widths); 561               562 3         7 for my $column (0 .. $#$headers) 563             { 564 15         160 @column = ($$headers[$column], $$footers[$column]); 565               566 15         31 for my $row (0 .. $#$data) 567             { 568 60         99 push @column, $$data[$row][$column]; 569             } 570               571 15         30 push @max_widths, max map{ tty_width($_) } @column;   90         2745   572             } 573               574 3         102 $self -> widths(\@max_widths); 575               576             } # End of _gather_statistics. 577               578             # ------------------------------------------------ 579             # Ensure all header/data/footer rows are the same length. 580               581             sub _rectify_data 582             { 583 3     3   8 my($self, $alignment, $headers, $data, $footers) = @_; 584               585             # Note: include is not validated, since it's a set of bit fields. 586               587 3         50 $self -> _validate($self -> empty, empty_as_empty, empty_as_undef, 'empty'); 588 3         53 $self -> _validate($self -> escape, escape_nothing, escape_uri, 'escape'); 589 3         53 $self -> _validate($self -> extend_data, extend_with_empty, extend_with_undef, 'extend_data'); 590 3         52 $self -> _validate($self -> extend_footers, extend_with_empty, extend_with_undef, 'extend_headers'); 591 3         48 $self -> _validate($self -> extend_footers, extend_with_empty, extend_with_undef, 'extend_footers'); 592 3         47 $self -> _validate($self -> format, format_internal_boxed, format_text_unicodebox_table, 'format'); 593 3         51 $self -> _validate($self -> undef, undef_as_empty, undef_as_undef, 'undef'); 594               595 3         7 for my $alignment (@{$self -> alignment})   3         47   596             { 597 10         31 $self -> _validate($alignment, align_left, align_right, 'align'); 598             } 599               600             # Find the longest header/data/footer row. Ignore aligment. 601               602 3         12 my($max_length) = 0; 603               604 3         11 for my $row (0 .. $#$data) 605             { 606 12 100       16 $max_length = $#{$$data[$row]} if ($#{$$data[$row]} > $max_length);   3         8     12         44   607             } 608               609 3         16 $max_length = max $#$headers, $#$footers, $max_length; 610               611             # Shrink the alignment row if necessary. 612               613 3 50       8 $#$alignment = $max_length if ($#$alignment > $max_length); 614               615             # Now expand all rows to be the same, maximum, length. 616               617 3         10 my($filler) = align_center; 618 3         16 $$alignment[$_] = $filler for ($#$alignment + 1 .. $max_length); 619 3 50       57 $filler = ($self -> extend_headers == extend_with_empty) ? '' : undef; 620 3         36 $$headers[$_] = $filler for ($#$headers + 1 .. $max_length); 621 3 50       47 $filler = ($self -> extend_footers == extend_with_empty) ? '' : undef; 622 3         32 $$footers[$_] = $filler for ($#$footers + 1 .. $max_length); 623 3 50       48 $filler = ($self -> extend_data == extend_with_empty) ? '' : undef; 624               625 3         28 for my $row (0 .. $#$data) 626             { 627 12         21 $$data[$row][$_] = $filler for ($#{$$data[$row]} + 1 .. $max_length);   12         25   628             } 629               630             } # End of _rectify_data. 631               632             # ------------------------------------------------ 633               634             sub render 635             { 636 3     3 1 1893 my($self, %hash) = @_; 637               638             # Process parameters passed to render(), which can be the same as to new(). 639               640 3         11 for my $key (keys %hash) 641             { 642 0         0 $self -> $key($hash{$key}); 643             } 644               645 3         74 my($alignment) = $self -> alignment; 646 3         64 my($headers) = $self -> headers; 647 3         58 my($data) = $self -> data; 648 3         70 my($footers) = $self -> footers; 649 3         59 my($format) = $self -> format; 650               651 3         24 $self -> _gather_statistics($alignment, $headers, $data, $footers); 652               653 3         88 my($output); 654               655 3 100       10 if ($format == format_internal_boxed)     100               50               0               0               0           656             { 657 1         9 $output = $self -> format_as_internal_boxed($alignment, $headers, $data, $footers); 658             } 659             elsif ($format == format_internal_github) 660             { 661 1         32 $output = $self -> format_as_internal_github($alignment, $headers, $data, $footers); 662             } 663             elsif ($format == format_internal_html) 664             { 665 1         13 $output = $self -> format_as_internal_html($alignment, $headers, $data, $footers); 666             } 667             elsif ($format == format_html_table) 668             { 669 0         0 $output = $self -> format_as_html_table($alignment, $headers, $data, $footers); 670             } 671             elsif ($format == format_text_csv) 672             { 673 0         0 $output = $self -> format_as_text_csv($alignment, $headers, $data, $footers); 674             } 675             elsif ($format == format_text_unicodebox_table) 676             { 677 0         0 $output = $self -> format_as_text_unicodebox_table($alignment, $headers, $data, $footers); 678             } 679             else 680             { 681 0         0 die 'Error: format not implemented: ' . $format . "\n"; 682             } 683               684 3         16 return $output; 685               686             } # End of render. 687               688             # ------------------------------------------------ 689               690             sub render_as_string 691             { 692 0     0 1 0 my($self, %hash) = @_; 693 0 0       0 my($join) = defined($hash{join}) ? $hash{join} : $self -> join; 694               695 0         0 return join($join, @{$self -> render(%hash)});   0         0   696               697             } # End of render_as_string. 698               699             # ------------------------------------------------ 700               701             sub _validate 702             { 703 31     31   241 my($self, $value, $min, $max, $name) = @_; 704               705 31 50 33     111 if ( ($value < $min) || ($value > $max) ) 706             { 707 0           die "Error. The value for '$name', $value, is out of the range ($min .. $max)\n"; 708             } 709               710             } # End of _validate. 711               712             # ------------------------------------------------ 713               714             1; 715               716             =pod 717               718             =encoding utf8 719               720             =head1 NAME 721               722             C - Render tables in manifold formats 723               724             =head1 Synopsis 725               726             This is scripts/synopsis.pl: 727               728             #!/usr/bin/env perl 729               730             use strict; 731             use utf8; 732             use warnings; 733             use warnings qw(FATAL utf8); # Fatalize encoding glitches. 734             use open qw(:std :utf8); # Undeclared streams in UTF-8. 735               736             use Text::Table::Manifold ':constants'; 737               738             # ----------- 739               740             # Set parameters with new(). 741               742             my($table) = Text::Table::Manifold -> new 743             ( 744             alignment => 745             [ 746             align_left, 747             align_center, 748             align_right, 749             align_center, 750             ] 751             ); 752               753             $table -> headers(['Homepage', 'Country', 'Name', 'Metadata']); 754             $table -> data( 755             [ 756             ['http://savage.net.au/', 'Australia', 'Ron Savage', undef], 757             ['https://duckduckgo.com/', 'Earth', 'Mr. S. Engine', ''], 758             ]); 759               760             # Note: Save the data, since render() may update it. 761               762             my(@data) = @{$table -> data}; 763               764             # Set parameters with methods. 765               766             $table -> empty(empty_as_text); 767             $table -> format(format_internal_boxed); 768             $table -> undef(undef_as_text); 769               770             # Set parameters with render(). 771               772             print "Format: format_internal_boxed: \n"; 773             print join("\n", @{$table -> render(padding => 1)}), "\n"; 774             print "\n"; 775               776             $table -> headers(['One', 'Two', 'Three']); 777             $table -> data( 778             [ 779             ['Reichwaldstraße', 'Böhme', 'ʎ ʏ ʐ ʑ ʒ ʓ ʙ ʚ'], 780             ['ΔΔΔΔΔΔΔΔΔΔ', 'Πηληϊάδεω Ἀχιλῆος', 'A snowman: ☃'], 781             ['Two ticks: ✔✔', undef, '
TBA
'], 782             ]); 783               784             # Save the data, since render() may update it. 785               786             @data = @{$table -> data}; 787               788             $table -> empty(empty_as_minus); 789             $table -> format(format_internal_boxed); 790             $table -> undef(undef_as_text); 791             $table -> padding(2); 792               793             print "Format: format_internal_boxed: \n"; 794             print join("\n", @{$table -> render}), "\n"; 795             print "\n"; 796               797             # Restore the saved data. 798               799             $table -> data([@data]); 800               801             # Etc. 802               803             This is data/synopsis.log, the output of synopsis.pl: 804               805             Format: format_internal_boxed: 806             +-------------------------+-----------+---------------+----------+ 807             | Homepage | Country | Name | Metadata | 808             +-------------------------+-----------+---------------+----------+ 809             | http://savage.net.au/ | Australia | Ron Savage | undef | 810             | https://duckduckgo.com/ | Earth | Mr. S. Engine | empty | 811             +-------------------------+-----------+---------------+----------+ 812               813             Format: format_internal_boxed: 814             +-------------------+---------------------+----------------------------------------+ 815             | One | Two | Three | 816             +-------------------+---------------------+----------------------------------------+ 817             | Reichwaldstraße | Böhme | ʎ ʏ ʐ ʑ ʒ ʓ ʙ ʚ | 818             | ΔΔΔΔΔΔΔΔΔΔ | Πηληϊάδεω Ἀχιλῆος | A snowman: ☃ | 819             | Two ticks: ✔✔ | undef |
TBA
| 820             +-------------------+---------------------+----------------------------------------+ 821               822             The latter table renders perfectly in FF, but not so in Chrome (today, 2015-01-31). 823               824             =head1 Description 825               826             Outputs tables in any one of several supported types. 827               828             Features: 829               830             =over 4 831               832             =item o Generic interface to all supported table formats 833               834             =item o Separately specify header/data/footer rows 835               836             =item o Separately include/exclude header/data/footer rows 837               838             =item o Align cell values 839               840             Each column has its own alignment option, left, center or right. 841               842             For internally generated HTML, this is done with a CSS C
within each C, not with the obsolete 843             C attribute. 844               845             But decimal places are not alignable, yet, as discussed in the L. 846               847             =item o Escape HTML entities or URIs 848               849             But not both at the same time! 850               851             =item o Extend short header/data/footer rows with empty strings or undef 852               853             Auto-extension results in all rows being the same length. 854               855             This takes place before the transformation, if any, mentioned next. 856               857             =item o Tranform cell values which are empty strings and undef 858               859             =item o Pad cell values 860               861             =item o Handle UFT8 862               863             =item o Return the table as an arrayref of lines or as a string 864               865             The arrayref is returned by L, and the string by L. 866               867             When returning a string by calling C (which calls C), you can specify 868             how the lines in the arrayref are joined. 869               870             In the same way the C parameter discussed just below controls the output, the C 871             parameter controls the join. 872               873             =back 874               875             The format of the output is controlled by the C parameter to C, or by the parameter 876             to the L method, or by the value of the C key in the hash passed to 877             L and L, and must be one of these imported constants: 878               879             =over 4 880               881             =item o format_internal_boxed 882               883             All headers, footers and table data are surrounded by ASCII characters. 884               885             The rendering is done internally. 886               887             See scripts/internal.boxed.pl and output file data/internal.boxed.log. 888               889             =item o format_internal_github 890               891             Render as github-flavoured markdown. 892               893             The rendering is done internally. 894               895             See scripts/internal.github.pl and output file data/internal.github.log. 896               897             =item o format_internal_html 898               899             Render as a HTML table. You can use the L method to set options for the HTML 900             table. 901               902             The rendering is done internally. 903               904             See scripts/internal.html.pl and output file data/internal.html.log. 905               906             =item o format_html_table 907               908             Passes the data to L. You can use the L method to set options 909             for the C object constructor. 910               911             Warning: You must use C's C method, or the C parameter to 912             C, and not the C<-data> option to C. This is because the module processes the 913             data before calling the C constructor. 914               915             =item o format_text_csv 916               917             Passes the data to L. You can use the L method to set options for 918             the C object constructor. 919               920             See scripts/text.csv.pl and output file data/text.csv.log. 921               922             =item o format_text_unicodebox_table 923               924             Passes the data to L. You can use the L method to 925             set options for the C object constructor. 926               927             See scripts/text.unicodebox.table.pl and output file data/text.unicodebox.table.log. 928               929             =back 930               931             See also scripts/synopsis.pl, and the output data/synopsis.log. 932               933             =head1 Distributions 934               935             This module is available as a Unix-style distro (*.tgz). 936               937             See L 938             for help on unpacking and installing distros. 939               940             =head1 Installation 941               942             Install L as you would any C module: 943               944             Run: 945               946             cpanm Text::Table::Manifold 947               948             or run: 949               950             sudo cpan Text::Table::Manifold 951               952             or unpack the distro, and then either: 953               954             perl Build.PL 955             ./Build 956             ./Build test 957             sudo ./Build install 958               959             or: 960               961             perl Makefile.PL 962             make (or dmake or nmake) 963             make test 964             make install 965               966             =head1 Constructor and Initialization 967               968             C is called as C<< my($parser) = Text::Table::Manifold -> new(k1 => v1, k2 => v2, ...) >>. 969               970             It returns a new object of type C. 971               972             Details of all parameters are explained in the L. 973               974             Key-value pairs accepted in the parameter list (see corresponding methods for details 975             [e.g. L]): 976               977             =over 4 978               979             =item o alignment => $arrayref of imported constants 980               981             This specifies alignment per column. There should be one array element per column of data. The 982             $arrayref will be auto-extended if necessary, using the constant C. 983               984             Alignment applies equally to every cell in the column. 985               986             A value for this parameter is optional. 987               988             Default: align_center for every column. 989               990             =item o data => $arrayref_of_arrayrefs 991               992             This specifies the table of cell values. 993               994             An arrayref of arrayrefs, each inner arrayref is a row of data. 995               996             The # of elements in each alignment/header/data/footer row does not have to be the same. See the 997             C parameters for more. Auto-extension results in all rows being the same length. 998               999             A value for this parameter is optional. 1000               1001             Default: []. 1002               1003             =item o empty => An imported constant 1004               1005             This specifies how to transform cell values which are the empty string. See also the C 1006             parameter. 1007               1008             The C parameter is activated after the C parameters has been applied. 1009               1010             A value for this parameter is optional. 1011               1012             Default: empty_as_empty. I.e. do not transform. 1013               1014             =item o escape => An imported constant 1015               1016             This specifies escaping of either HTML entities or URIs. 1017               1018             A value for this parameter is optional. 1019               1020             Default: escape_nothing. I.e. do not transform. 1021               1022             =item o extend_data => An imported constant 1023               1024             The 2 constants available allow you to specify how short data rows are extended. Then, after 1025             extension, the transformations specified by the parameters C and C are applied. 1026               1027             A value for this parameter is optional. 1028               1029             Default: extend_with_empty. I.e. extend short data rows with the empty string. 1030               1031             =item o extend_footers => An imported constant 1032               1033             The 2 constants available allow you to specify how short footer rows are extended. Then, after 1034             extension, the transformations specified by the parameters C and C are applied. 1035               1036             A value for this parameter is optional. 1037               1038             Default: extend_with_empty. I.e. extend short footer rows with the empty string. 1039               1040             =item o extend_headers => An imported constant 1041               1042             The 2 constants available allow you to specify how short header rows are extended. Then, after 1043             extension, the transformations specified by the parameters C and C are applied. 1044               1045             A value for this parameter is optional. 1046               1047             Default: extend_with_empty. I.e. extend short header rows with the empty string. 1048               1049             =item o footers => $arrayref 1050               1051             These are the column footers. See also the C option. 1052               1053             The # of elements in each header/data/footer row does not have to be the same. See the C 1054             parameters for more. 1055               1056             A value for this parameter is optional. 1057               1058             Default: []. 1059               1060             =item o format => An imported constant 1061               1062             This specifies which format to output from the rendering methods. 1063               1064             A value for this parameter is optional. 1065               1066             Default: format_internal_boxed. 1067               1068             =item o headers => $arrayref 1069               1070             These are the column headers. See also the C option. 1071               1072             The # of elements in each header/data/footer row does not have to be the same. See the C 1073             parameters for more. 1074               1075             A value for this parameter is optional. 1076               1077             Default: []. 1078               1079             =item o include => An imported constant 1080               1081             Controls whether header/data/footer rows are included in the output. 1082               1083             The are three constants available, and any of them can be combined with '|', the logical OR 1084             operator. 1085               1086             A value for this parameter is optional. 1087               1088             Default: include_headers | include_data. 1089               1090             =item o join => $string 1091               1092             L uses $hash{join}, or $self -> join, in Perl's 1093             C to join the elements of the arrayref returned by internally calling 1094             L. 1095               1096             C ignores the C key in the hash. 1097               1098             A value for this parameter is optional. 1099               1100             Default: ''. 1101               1102             =item o padding => $integer 1103               1104             This integer is the # of spaces added to each side of the cell value, after the C 1105             parameter has been applied. 1106               1107             A value for this parameter is optional. 1108               1109             Default: 0. 1110               1111             =item o pass_thru => $hashref 1112               1113             A hashref of values to pass thru to another object. 1114               1115             The keys in this $hashref control what parameters are passed to rendering routines. 1116               1117             A value for this parameter is optional. 1118               1119             Default: {}. 1120               1121             =item o undef => An imported constant 1122               1123             This specifies how to transform cell values which are undef. See also the C parameter. 1124               1125             The C parameter is activated after the C parameters have been applied. 1126               1127             A value for this parameter is optional. 1128               1129             Default: undef_as_undef. I.e. do not transform. 1130               1131             =back 1132               1133             =head1 Methods 1134               1135             See the L for details of all importable constants mentioned here. 1136               1137             And remember, all methods listed here which are parameters to L, are also parameters 1138             to both L and L. 1139               1140             =head2 alignment([$arrayref]) 1141               1142             Here, the [] indicate an optional parameter. 1143               1144             Returns the alignment as an arrayref of constants, one per column. 1145               1146             There should be one element in $arrayref for each column of data. If the $arrayref is too short, 1147             C is the default for the missing alignments. 1148               1149             Obviously, $arrayref might force spaces to be added to one or both sides of a cell value. 1150               1151             Alignment applies equally to every cell in the column. 1152               1153             This happens before any spaces specified by L are added. 1154               1155             See the L for legal values for the alignments (per 1156             column). 1157               1158             C is a parameter to L. See L. 1159               1160             =head2 data([$arrayref]) 1161               1162             Here, the [] indicate an optional parameter. 1163               1164             Returns the data as an arrayref. Each element in this arrayref is an arrayref of one row of data. 1165               1166             The structure of C<$arrayref>, if provided, must match the description in the previous line. 1167               1168             Rows do not need to have the same number of elements. 1169               1170             Use Perl's C or '' (the empty string) for missing values. 1171               1172             See L and L for how '' and C are handled. 1173               1174             See L for how to extend short data rows, or let the code extend auto-extend 1175             them. 1176               1177             C is a parameter to L. See L. 1178               1179             =head2 empty([$empty]) 1180               1181             Here, the [] indicate an optional parameter. 1182               1183             Returns the option specifying how empty cell values ('') are being dealt with. 1184               1185             $empty controls how empty strings in cells are rendered. 1186               1187             See the L 1188             for legal values for $empty. 1189               1190             See also L. 1191               1192             C is a parameter to L. See L. 1193               1194             =head2 escape([$escape]) 1195               1196             Here, the [] indicate an optional parameter. 1197               1198             Returns the option specifying how HTML entities and URIs are being dealt with. 1199               1200             $escape controls how either HTML entities or URIs are rendered. 1201               1202             See the L 1203             for legal values for $escape. 1204               1205             C is a parameter to L. See L. 1206               1207             =head2 extend_data([$extend]) 1208               1209             Here, the [] indicate an optional parameter. 1210               1211             Returns the option specifying how short data rows are extended. 1212               1213             If the # of elements in a data row is shorter than the longest row, $extend 1214             specifies how to extend those short rows. 1215               1216             See the L for legal values for $extend. 1217               1218             C is a parameter to L. See L. 1219               1220             =head2 extend_footers([$extend]) 1221               1222             Here, the [] indicate an optional parameter. 1223               1224             Returns the option specifying how short footer rows are extended. 1225               1226             If the # of elements in a footer row is shorter than the longest row, $extend 1227             specifies how to extend those short rows. 1228               1229             See the L for legal values for $extend. 1230               1231             C is a parameter to L. See L. 1232               1233             =head2 extend_headers([$extend]) 1234               1235             Here, the [] indicate an optional parameter. 1236               1237             Returns the option specifying how short header rows are extended. 1238               1239             If the # of elements in a header row is shorter than the longest row, $extend 1240             specifies how to extend those short rows. 1241               1242             See the L for legal values for $extend. 1243               1244             C is a parameter to L. See L. 1245               1246             =head2 footers([$arrayref]) 1247               1248             Here, the [] indicate an optional parameter. 1249               1250             Returns the footers as an arrayref of strings. 1251               1252             $arrayref, if provided, must be an arrayref of strings. 1253               1254             See L for how to extend a short footer row, or let the code auto-extend 1255             it. 1256               1257             C is a parameter to L. See L. 1258               1259             =head2 format([$format]) 1260               1261             Here, the [] indicate an optional parameter. 1262               1263             Returns the format as a constant (actually an integer). 1264               1265             See the L for legal values for $format. 1266               1267             C is a parameter to L. See L. 1268               1269             =head2 format_as_internal_boxed() 1270               1271             Called by L. 1272               1273             =head2 format_as_internal_github() 1274               1275             Called by L. 1276               1277             =head2 format_as_internal_html() 1278               1279             Called by L. 1280               1281             =head2 format_as_html_table() 1282               1283             Called by L. 1284               1285             =head2 format_as_text_csv(). 1286               1287             Called by L. 1288               1289             =head2 format_as_text_unicodebox_table() 1290               1291             Called by L. 1292               1293             =head2 headers([$arrayref]) 1294               1295             Here, the [] indicate an optional parameter. 1296               1297             Returns the headers as an arrayref of strings. 1298               1299             $arrayref, if provided, must be an arrayref of strings. 1300               1301             See L for how to extend a short header row, or let the code auto-extend 1302             it. 1303               1304             C is a parameter to L. See L. 1305               1306             =head2 include([$include]) 1307               1308             Here, the [] indicate an optional parameter. 1309               1310             Returns the option specifying if header/data/footer rows are included in the output. 1311               1312             See the L for legal values 1313             for $include. 1314               1315             C is a parameter to L. See L. 1316               1317             =head2 join([$join]) 1318               1319             Here, the [] indicate an optional parameter. 1320               1321             Returns the string used to join lines in the table when you call L. 1322               1323             $join is the parameter passed to the Perl function C by C. 1324               1325             Further, you can use the key C in %hash to pass a value directly to 1326             L. 1327               1328             =head2 new([%hash]) 1329               1330             The constructor. See L for details of the parameter list. 1331               1332             Note: L and Lsupport the same options as C. 1333               1334             =head2 padding([$integer]) 1335               1336             Here, the [] indicate an optional parameter. 1337               1338             Returns the padding as an integer. 1339               1340             Padding is the # of spaces to add to both sides of the cell value after it has been aligned. 1341               1342             C is a parameter to L. See L. 1343               1344             =head2 pass_thru([$hashref]) 1345               1346             Here, the [] indicate an optional parameter. 1347               1348             Returns the hashref previously provided. 1349               1350             See L for details. 1351               1352             See scripts/html.table.pl, scripts/internal.table.pl and scripts/text.csv.pl for sample code where 1353             it is used in various ways. 1354               1355             C is a parameter to L. See L. 1356               1357             =head2 render([%hash]) 1358               1359             Here, the [] indicate an optional parameter. 1360               1361             Returns an arrayref, where each element is 1 line of the output table. These lines do not have "\n" 1362             or any other line terminator added by this module. 1363               1364             It's up to you how to handle the output. The simplest thing is to just do: 1365               1366             print join("\n", @{$table -> render}), "\n"; 1367               1368             Note: C supports the same options as L. 1369               1370             C ignores the C key in the hash. 1371               1372             See also L. 1373               1374             =head2 render_as_string([%hash]) 1375               1376             Here, the [] indicate an optional parameter. 1377               1378             Returns the rendered data as a string. 1379               1380             C uses the value of $hash{join}, or the result of calling $self -> join, in Perl's 1381             C to join the elements of the arrayref returned by internally calling 1382             L. 1383               1384             Note: C supports the same options as L, and passes them all to 1385             L. 1386               1387             See also L. 1388               1389             =head2 undef([$undef]) 1390               1391             Here, the [] indicate an optional parameter. 1392               1393             Returns the option specifying how undef cell values are being dealt with. 1394               1395             $undef controls how undefs in cells are rendered. 1396               1397             See the L 1398             for legal values for $undef. 1399               1400             See also L. 1401               1402             C is a parameter to L. See L. 1403               1404             =head2 widths() 1405               1406             Returns an arrayref of the width of each column, after the data is cleaned and rectified, but before 1407             it has been aligned or padded. 1408               1409             =head1 FAQ 1410               1411             Note: See L for what has not been implemented yet. 1412               1413             =head2 How are imported constants used? 1414               1415             Firstly, you must import them with: 1416               1417             use Text::Table::Manifold ':constants'; 1418               1419             Then you can use them in the constructor: 1420               1421             my($table) = Text::Table::Manifold -> new(empty => empty_as_text); 1422               1423             And/or you can use them in method calls: 1424               1425             $table -> format(format_internal_boxed); 1426               1427             See scripts/synopsis.pl for various use cases. 1428               1429             Note how sample code uses the names of the constants. The integer values listed below are just FYI. 1430               1431             =head2 What are the constants for alignment? 1432               1433             The parameters, one per column, to L must be one of the following: 1434               1435             =over 4 1436               1437             =item o align_left => 0 1438               1439             =item o align_center => 1 1440               1441             So-spelt. Not 'centre'. 1442               1443             =item o align_right => 2 1444               1445             =back 1446               1447             Alignment applies equally to every cell in a column. 1448               1449             =head2 What are the constants for handling cell values which are empty strings? 1450               1451             The parameter to L must be one of the following: 1452               1453             =over 4 1454               1455             =item o empty_as_empty => 0 1456               1457             Do nothing. This is the default. 1458               1459             =item o empty_as_minus => 1 1460               1461             Convert empty cell values to '-'. 1462               1463             =item o empty_as_text => 2 1464               1465             Convert empty cell values to the text string 'empty'. 1466               1467             =item o empty_as_undef => 3 1468               1469             Convert empty cell values to undef. 1470               1471             =back 1472               1473             See also L. 1474               1475             Warning: This updates the original data! 1476               1477             =head2 What are the constants for escaping HTML entities and URIs? 1478               1479             The parameter to L must be one of the following: 1480               1481             =over 4 1482               1483             =item o escape_nothing => 0 1484               1485             This is the default. 1486               1487             =item o escape_html => 1 1488               1489             Use L to escape HTML entities. C cannot 1490             be loaded at runtime, and so is always needed. 1491               1492             =item o escape_uri => 2 1493               1494             Use L's uri_escape() method to escape URIs. C is loaded at runtime 1495             if needed. 1496               1497             =back 1498               1499             Warning: This updates the original data! 1500               1501             =head2 What are the constants for extending short rows? 1502               1503             The parameters to L, L and 1504             L, must be one of the following: 1505               1506             =over 4 1507               1508             =item o extend_with_empty => 0 1509               1510             Short header/data/footer rows are extended with the empty string. 1511               1512             Later, the values discussed under 1513             L will be applied. 1514               1515             =item o extend_with_undef => 1 1516               1517             Short header/data/footer rows are extended with undef. 1518               1519             Later, the values discussed under 1520             L will be applied. 1521               1522             =back 1523               1524             See also L and L. 1525               1526             Warning: This updates the original data! 1527               1528             =head2 What are the constants for formatting? 1529               1530             The parameter to L must be one of the following: 1531               1532             =over 4 1533               1534             =item o format_internal_boxed => 0 1535               1536             Render internally. 1537               1538             =item o format_text_csv => 1 1539               1540             L is loaded at runtime if this option is used. 1541               1542             =item o format_internal_github => 2 1543               1544             Render internally. 1545               1546             =item o format_internal_html => 3 1547               1548             Render internally. 1549               1550             =item o format_html_table => 4 1551               1552             L is loaded at runtime if this option is used. 1553               1554             =item o format_text_unicodebox_table => 5 1555               1556             L is loaded at runtime if this option is used. 1557               1558             =back 1559               1560             =head2 What are the constants for including/excluding rows in the output? 1561               1562             The parameter to L must be one or more of the following: 1563               1564             =over 4 1565               1566             =item o include_data => 1 1567               1568             Data rows are included in the output. 1569               1570             =item o include_footers => 2 1571               1572             Footer rows are included in the output. 1573               1574             =item o include_headers => 4 1575               1576             Header rows are included in the output. 1577               1578             =back 1579               1580             =head2 What is the format of the $hashref used in the call to pass_thru()? 1581               1582             It takes these (key => value) pairs: 1583               1584             =over 4 1585               1586             =item o new => $hashref 1587               1588             =over 4 1589               1590             =item o For internal rendering of HTML 1591               1592             $$hashref{table} is used to specify parameters for the C tag.
1593              
1594             Currently, C is the only tag supported by this mechanism.
1595              
1596             =item o When using L, for external rendering of HTML
1597              
1598             $hashref is passed to the L constructor.
1599              
1600             =item o When using L, for external rendering of CSV
1601              
1602             $hashref is passed to the L constructor.
1603              
1604             =item o When using L, for external rendering of boxes
1605              
1606             $hashref is passed to the L constructor.
1607              
1608             =back
1609              
1610             =back
1611              
1612             See html.table.pl, internal.html.pl and text.csv.pl, all in the scripts/ directory.
1613              
1614             =head2 What are the constants for handling cell values which are undef?
1615              
1616             The parameter to L must be one of the following:
1617              
1618             =over 4
1619              
1620             =item o undef_as_empty => 0
1621              
1622             Convert undef cell values to the empty string ('').
1623              
1624             =item o undef_as_minus => 1
1625              
1626             Convert undef cell values to '-'.
1627              
1628             =item o undef_as_text => 2
1629              
1630             Convert undef cell values to the text string 'undef'.
1631              
1632             =item o undef_as_undef => 3
1633              
1634             Do nothing.
1635              
1636             This is the default.
1637              
1638             =back
1639              
1640             See also L.
1641              
1642             Warning: This updates the original data!
1643              
1644             =head2 Will you extend the program to support other external renderers?
1645              
1646             Possibly, but only if the extension matches the spirit of this module, which is roughly: Keep it
1647             simple, and provide just enough options but not too many options. IOW, there is no point in passing
1648             a huge number of options to an external class when you can use that class directly anyway.
1649              
1650             I've looked a number of times at L, for example, but it is just a little bit too
1651             complex. Similarly, L has too many methods.
1652              
1653             See also L.
1654              
1655             =head2 How do I run author tests?
1656              
1657             This runs both standard and author tests:
1658              
1659             shell> perl Build.PL; ./Build; ./Build authortest
1660              
1661             =head1 TODO
1662              
1663             =over 4
1664              
1665             =item o Fancy alignment of real numbers
1666              
1667             It makes sense to right-justify integers, but in the rest of the table you probably want to
1668             left-justify strings.
1669              
1670             Then, vertically aligning decimal points (whatever they are in your locale) is another complexity.
1671              
1672             See L and L.
1673              
1674             =item o Embedded newlines
1675              
1676             Cell values could be split at each "\n" character, to find the widest line within the cell. That
1677             would be then used as the cell's width.
1678              
1679             For Unicode, this is complex. See L, and
1680             especially p 192, for 'Line break' controls. Also, the Unicode line breaking algorithm is documented
1681             in L.
1682              
1683             Perl modules and other links relevant to this topic are listed under L.
1684              
1685             =item o Nested tables
1686              
1687             This really requires the implementation of embedded newline analysis, as per the previous point.
1688              
1689             =item o Pass-thru class support
1690              
1691             The problem is the mixture of options required to drive classes.
1692              
1693             =item o Sorting the rows, or individual columns
1694              
1695             See L and L.
1696              
1697             =item o Color support
1698              
1699             See L.
1700              
1701             =item o Subtotal support
1702              
1703             Maybe one day. I did see a subtotal feature in a module while researching this, but I can't find it
1704             any more.
1705              
1706             See L. It has grouping features.
1707              
1708             =back
1709              
1710             =head1 See Also
1711              
1712             =head2 Table Rendering
1713              
1714             L
1715              
1716             L
1717              
1718             L
1719              
1720             L
1721              
1722             L
1723              
1724             L
1725              
1726             L
1727              
1728             L
1729              
1730             L
1731              
1732             L
1733              
1734             L
1735              
1736             L
1737              
1738             L
1739              
1740             L
1741              
1742             L
1743              
1744             L
1745              
1746             L
1747              
1748             L
1749              
1750             L
1751              
1752             L
1753              
1754             L
1755              
1756             L
1757              
1758             L
1759              
1760             L
1761              
1762             L
1763              
1764             L
1765              
1766             L
1767              
1768             L
1769              
1770             =head2 Line Breaking
1771              
1772             L
1773              
1774             L
1775              
1776             L
1777              
1778             L
1779              
1780             L
1781              
1782             L.
1783              
1784             L
1785              
1786             =head1 Machine-Readable Change Log
1787              
1788             The file Changes was converted into Changelog.ini by L.
1789              
1790             =head1 Version Numbers
1791              
1792             Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.
1793              
1794             =head1 Repository
1795              
1796             L
1797              
1798             =head1 Support
1799              
1800             Email the author, or log a bug on RT:
1801              
1802             L.
1803              
1804             =head1 Author
1805              
1806             L was written by Ron Savage Iron@savage.net.auE> in 2015.
1807              
1808             Marpa's homepage: L.
1809              
1810             My homepage: L.
1811              
1812             =head1 Copyright
1813              
1814             Australian copyright (c) 2014, Ron Savage.
1815              
1816             All Programs of mine are 'OSI Certified Open Source Software';
1817             you can redistribute them and/or modify them under the terms of
1818             The Perl Artistic License, a copy of which is available at:
1819             https://perldoc.perl.org/perlartistic.html.
1820              
1821             =cut