File Coverage

lib/OODoc/Format/Pod.pm
Criterion Covered Total %
statement 51 286 17.8
branch 19 198 9.6
condition 0 12 0.0
subroutine 10 34 29.4
pod 17 25 68.0
total 97 555 17.4


line stmt bran cond sub pod time code
1             # Copyrights 2003-2015 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.01.
5             package OODoc::Format::Pod;
6 2     2   24105 use vars '$VERSION';
  2         4  
  2         118  
7             $VERSION = '2.01';
8              
9 2     2   9 use base 'OODoc::Format';
  2         4  
  2         546  
10              
11 2     2   10 use strict;
  2         4  
  2         43  
12 2     2   10 use warnings;
  2         4  
  2         54  
13              
14 2     2   9 use Log::Report 'oodoc';
  2         4  
  2         15  
15              
16 2     2   508 use File::Spec ();
  2         4  
  2         51  
17 2     2   10 use List::Util qw/max/;
  2         4  
  2         123  
18 2     2   1660 use Pod::Escapes qw/e2char/;
  2         7151  
  2         8395  
19              
20              
21             sub link($$;$)
22 0     0 1 0 { my ($self, $manual, $object, $text) = @_;
23              
24 0 0       0 $object = $object->subroutine if $object->isa('OODoc::Text::Option');
25 0 0       0 $object = $object->subroutine if $object->isa('OODoc::Text::Default');
26 0 0       0 $object = $object->container if $object->isa('OODoc::Text::Example');
27 0 0       0 $object = $object->container if $object->isa('OODoc::Text::Subroutine');
28 0 0       0 $text = defined $text ? "$text|" : '';
29              
30 0 0       0 return "L<$text$object>"
31             if $object->isa('OODoc::Manual');
32              
33 0 0       0 $object->isa('OODoc::Text::Structure')
34             or error __x"cannot link to a {pkg}", pkg => ref $object;
35              
36 0 0       0 my $manlink = defined $manual ? $object->manual.'/' : '';
37 0         0 qq(L<$text$manlink"$object">);
38             }
39              
40              
41             sub createManual($@)
42 0     0 1 0 { my ($self, %args) = @_;
43 0 0       0 my $manual = $args{manual} or panic;
44 0   0     0 my $options = $args{format_options} || [];
45              
46 0         0 my $podname = $manual->source;
47 0         0 $podname =~ s/\.pm$/.pod/;
48 0         0 my $tmpname = $podname . 't';
49              
50 0         0 my $tmpfile = File::Spec->catfile($self->workdir, $tmpname);
51 0         0 my $podfile = File::Spec->catfile($self->workdir, $podname);
52              
53 0 0       0 my $output = IO::File->new($tmpfile, "w")
54             or fault __x"cannot write prelimary pod manual to {file}"
55             , file => $tmpfile;
56              
57             $self->formatManual
58             ( manual => $manual
59             , output => $output
60             , append => $args{append}
61 0         0 , @$options
62             );
63              
64 0         0 $output->close;
65              
66 0         0 $self->cleanupPOD($tmpfile, $podfile);
67 0         0 unlink $tmpfile;
68              
69 0         0 $self->manifest->add($podfile);
70              
71 0         0 $self;
72             }
73              
74              
75             sub formatManual(@)
76 0     0 1 0 { my $self = shift;
77 0         0 $self->chapterName(@_);
78 0         0 $self->chapterInheritance(@_);
79 0         0 $self->chapterSynopsis(@_);
80 0         0 $self->chapterDescription(@_);
81 0         0 $self->chapterOverloaded(@_);
82 0         0 $self->chapterMethods(@_);
83 0         0 $self->chapterExports(@_);
84 0         0 $self->chapterDetails(@_);
85 0         0 $self->chapterDiagnostics(@_);
86 0         0 $self->chapterReferences(@_);
87 0         0 $self->chapterCopyrights(@_);
88 0         0 $self->showAppend(@_);
89 0         0 $self;
90             }
91              
92             sub showAppend(@)
93 0     0 0 0 { my ($self, %args) = @_;
94 0         0 my $append = $args{append};
95              
96 0 0       0 if(!defined $append) { ; }
    0          
97 0         0 elsif(ref $append eq 'CODE') { $append->(formatter => $self, %args) }
98             else
99 0 0       0 { my $output = $args{output} or panic;
100 0         0 $output->print($append);
101             }
102              
103 0         0 $self;
104             }
105              
106             sub showStructureExpand(@)
107 0     0 0 0 { my ($self, %args) = @_;
108              
109 0   0     0 my $examples = $args{show_chapter_examples} || 'EXPAND';
110 0 0       0 my $text = $args{structure} or panic;
111              
112 0         0 my $name = $text->name;
113 0         0 my $level = $text->level;
114 0 0       0 my $output = $args{output} or panic;
115 0 0       0 my $manual = $args{manual} or panic;
116              
117 0         0 my $descr = $self->cleanup($manual, $text->description);
118 0         0 $output->print("\n=head$level $name\n\n$descr");
119              
120 0         0 $self->showSubroutines(%args, subroutines => [$text->subroutines]);
121 0 0       0 $self->showExamples(%args, examples => [$text->examples])
122             if $examples eq 'EXPAND';
123              
124 0         0 return $self;
125             }
126              
127             sub showStructureRefer(@)
128 0     0 1 0 { my ($self, %args) = @_;
129              
130 0 0       0 my $text = $args{structure} or panic;
131              
132 0         0 my $name = $text->name;
133 0         0 my $level = $text->level;
134 0 0       0 my $output = $args{output} or panic;
135 0 0       0 my $manual = $args{manual} or panic;
136              
137 0         0 my $link = $self->link($manual, $text);
138 0         0 $output->print("\n=head$level $name\n\nSee $link.\n");
139 0         0 $self;
140             }
141              
142             sub chapterDescription(@)
143 0     0 0 0 { my ($self, %args) = @_;
144              
145 0         0 $self->showRequiredChapter(DESCRIPTION => %args);
146              
147 0 0       0 my $manual = $args{manual} or panic;
148 0         0 my $details = $manual->chapter('DETAILS');
149            
150 0 0       0 return $self unless defined $details;
151              
152 0 0       0 my $output = $args{output} or panic;
153 0         0 $output->print("\nSee L chapter below\n");
154 0         0 $self->showChapterIndex($output, $details, " ");
155             }
156              
157             sub chapterDiagnostics(@)
158 0     0 0 0 { my ($self, %args) = @_;
159 0 0       0 my $manual = $args{manual} or panic;
160              
161 0         0 my $diags = $manual->chapter('DIAGNOSTICS');
162 0 0       0 $self->showChapter(chapter => $diags, %args)
163             if defined $diags;
164              
165 0         0 my @diags = map {$_->diagnostics} $manual->subroutines;
  0         0  
166 0 0       0 return unless @diags;
167              
168 0 0       0 my $output = $args{output} or panic;
169 0 0       0 $diags
170             or $output->print("\n=head1 DIAGNOSTICS\n");
171              
172 0         0 $output->print("\n=over 4\n\n");
173 0         0 $self->showDiagnostics(%args, diagnostics => \@diags);
174 0         0 $output->print("\n=back\n\n");
175 0         0 $self;
176             }
177              
178              
179             sub showChapterIndex($$;$)
180 0     0 1 0 { my ($self, $output, $chapter, $indent) = @_;
181 0 0       0 $indent = '' unless defined $indent;
182              
183 0         0 foreach my $section ($chapter->sections)
184 0         0 { $output->print($indent, $section->name, "\n");
185 0         0 foreach my $subsection ($section->subsections)
186 0         0 { $output->print($indent, $indent, $subsection->name, "\n");
187             }
188             }
189 0         0 $self;
190             }
191              
192             sub showExamples(@)
193 0     0 1 0 { my ($self, %args) = @_;
194 0 0       0 my $examples = $args{examples} or panic;
195 0 0       0 return unless @$examples;
196              
197 0 0       0 my $manual = $args{manual} or panic;
198 0 0       0 my $output = $args{output} or panic;
199              
200 0         0 foreach my $example (@$examples)
201 0         0 { my $name = $self->cleanup($manual, $example->name);
202 0         0 $output->print("\nexample: $name\n\n");
203 0         0 $output->print($self->cleanup($manual, $example->description));
204 0         0 $output->print("\n");
205             }
206 0         0 $self;
207             }
208              
209             sub showDiagnostics(@)
210 0     0 0 0 { my ($self, %args) = @_;
211 0 0       0 my $diagnostics = $args{diagnostics} or panic;
212 0 0       0 return unless @$diagnostics;
213              
214 0 0       0 my $manual = $args{manual} or panic;
215 0 0       0 my $output = $args{output} or panic;
216              
217 0         0 foreach my $diag (sort @$diagnostics)
218 0         0 { my $name = $self->cleanup($manual, $diag->name);
219 0         0 my $type = $diag->type;
220 0         0 $output->print("\n=item $type: $name\n\n");
221 0         0 $output->print($self->cleanup($manual, $diag->description));
222 0         0 $output->print("\n");
223             }
224 0         0 $self;
225             }
226              
227             sub showSubroutines(@)
228 0     0 1 0 { my ($self, %args) = @_;
229 0   0     0 my $subs = $args{subroutines} || [];
230 0 0       0 @$subs or return;
231              
232 0 0       0 my $output = $args{output} or panic;
233              
234 0         0 $output->print("\n=over 4\n\n");
235 0         0 $self->SUPER::showSubroutines(%args);
236 0         0 $output->print("\n=back\n\n");
237             }
238              
239             sub showSubroutine(@)
240 0     0 1 0 { my $self = shift;
241 0         0 $self->SUPER::showSubroutine(@_);
242              
243 0         0 my %args = @_;
244 0 0       0 my $output = $args{output} or panic;
245 0         0 $output->print("\n");
246 0         0 $self;
247             }
248              
249             sub showSubroutineUse(@)
250 0     0 1 0 { my ($self, %args) = @_;
251 0 0       0 my $subroutine = $args{subroutine} or panic;
252 0 0       0 my $manual = $args{manual} or panic;
253 0 0       0 my $output = $args{output} or panic;
254              
255 0         0 my $use = $self->subroutineUse($manual, $subroutine);
256 0         0 $use =~ s/(.+)/=item $1\n\n/gm;
257              
258 0         0 $output->print($use);
259 0 0       0 $output->print("Inherited, see ". $self->link($manual, $subroutine)."\n\n")
260             if $manual->inherited($subroutine);
261              
262 0         0 $self;
263             }
264              
265             sub subroutineUse($$)
266 0     0 0 0 { my ($self, $manual, $subroutine) = @_;
267 0         0 my $type = $subroutine->type;
268 0         0 my $name = $self->cleanup($manual, $subroutine->name);
269 0         0 my $paramlist = $self->cleanup($manual, $subroutine->parameters);
270 0 0       0 my $params
    0          
271             = !length $paramlist ? '()'
272             : $paramlist =~ m/^[\[<]|[\]>]$/ ? "( $paramlist )"
273             : "($paramlist)";
274              
275 0         0 my $class = $manual->package;
276 0 0       0 my $use
    0          
    0          
    0          
    0          
    0          
277             = $type eq 'i_method' ? qq[\$obj-EB<$name>$params]
278             : $type eq 'c_method' ? qq[$class-EB<$name>$params]
279             : $type eq 'ci_method'? qq[\$obj-EB<$name>$params\n]
280             . qq[$class-EB<$name>$params]
281             : $type eq 'function' ? qq[B<$name>$params]
282             : $type eq 'overload' ? qq[overload: B<$name>]
283             : $type eq 'tie' ? qq[B<$name>$params]
284             : '';
285              
286 0 0       0 length $use
287             or warn "WARNING: unknown subroutine type $type for $name in $manual";
288              
289 0         0 $use;
290             }
291              
292             sub showSubroutineName(@)
293 0     0 1 0 { my ($self, %args) = @_;
294 0 0       0 my $subroutine = $args{subroutine} or panic;
295 0 0       0 my $manual = $args{manual} or panic;
296 0 0       0 my $output = $args{output} or panic;
297 0         0 my $name = $subroutine->name;
298              
299 0 0       0 my $url
300             = $manual->inherited($subroutine)
301             ? "M<".$subroutine->manual."::$name>"
302             : "M<$name>";
303              
304             $output->print
305             ( $self->cleanup($manual, $url)
306 0 0       0 , ($args{last} ? ".\n" : ",\n")
307             );
308             }
309              
310             sub showOptions(@)
311 0     0 1 0 { my ($self, %args) = @_;
312 0 0       0 my $output = $args{output} or panic;
313 0         0 $output->print("\n=over 2\n\n");
314 0         0 $self->SUPER::showOptions(%args);
315 0         0 $output->print("\n=back\n\n");
316             }
317              
318             sub showOptionUse(@)
319 0     0 1 0 { my ($self, %args) = @_;
320 0 0       0 my $output = $args{output} or panic;
321 0 0       0 my $option = $args{option} or panic;
322 0 0       0 my $manual = $args{manual} or panic;
323              
324 0         0 my $params = $option->parameters;
325 0         0 $params =~ s/\s+$//;
326 0         0 $params =~ s/^\s+//;
327 0 0       0 $params = " => ".$self->cleanup($manual, $params) if length $params;
328            
329 0         0 $output->print("=item $option$params\n\n");
330 0         0 $self;
331             }
332              
333             sub showOptionExpand(@)
334 0     0 1 0 { my ($self, %args) = @_;
335 0 0       0 my $output = $args{output} or panic;
336 0 0       0 my $option = $args{option} or panic;
337 0 0       0 my $manual = $args{manual} or panic;
338              
339 0         0 $self->showOptionUse(%args);
340              
341 0 0       0 my $where = $option->findDescriptionObject or return $self;
342 0         0 my $descr = $self->cleanup($manual, $where->description);
343 0 0       0 $output->print("\n$descr\n\n")
344             if length $descr;
345              
346 0         0 $self;
347             }
348              
349              
350             sub writeTable($@)
351 0     0 1 0 { my ($self, %args) = @_;
352              
353 0 0       0 my $head = $args{header} or panic;
354 0 0       0 my $output = $args{output} or panic;
355 0 0       0 my $rows = $args{rows} or panic;
356 0 0       0 return unless @$rows;
357              
358             # Convert all elements to plain text, because markup is not
359             # allowed in verbatim pod blocks.
360 0         0 my @rows;
361 0         0 foreach my $row (@$rows)
362 0         0 { push @rows, [ map {$self->removeMarkup($_)} @$row ];
  0         0  
363             }
364              
365             # Compute column widths
366 0         0 my @w = (0) x @$head;
367              
368 0         0 foreach my $row ($head, @rows)
369             { $w[$_] = max $w[$_], length($row->[$_])
370 0         0 foreach 0..$#$row;
371             }
372              
373 0 0       0 if(my $widths = $args{widths})
374             { defined $widths->[$_] && $widths->[$_] > $w[$_] && ($w[$_] = $widths->[$_])
375 0   0     0 for 0..$#$rows;
      0        
376             }
377              
378 0         0 pop @w; # ignore width of last column
379              
380             # Table head
381 0         0 my $headf = " -".join("--", map { "\%-${_}s" } @w)."--%s\n";
  0         0  
382 0         0 $output->printf($headf, @$head);
383              
384             # Table body
385 0         0 my $format = " ".join(" ", map { "\%-${_}s" } @w)." %s\n";
  0         0  
386             $output->printf($format, @$_)
387 0         0 for @rows;
388             }
389              
390              
391             sub removeMarkup($)
392 20     20 1 45 { my ($self, $string) = @_;
393 20         44 my $out = $self->_removeMarkup($string);
394 20         38 for($out)
395 20         44 { s/^\s+//gm;
396 20         44 s/\s+$//gm;
397 20         33 s/\s{2,}/ /g;
398 20         39 s/\[NB\]/ /g;
399             }
400 20         91 $out;
401             }
402              
403             sub _removeMarkup($)
404 37     37   55 { my ($self, $string) = @_;
405              
406 37         47 my $out = '';
407 37         160 while($string =~ s/(.*?) # before
408             ([BCEFILSXZ]) # known formatting codes
409             ([<]+) # capture ALL starters
410             //x)
411 27         81 { $out .= $1;
412 27         66 my ($tag, $bracks, $brack_count) = ($2, $3, length($3));
413              
414 27 50       418 if($string !~ s/^(|.*?[^>]) # contained
415             [>]{$brack_count}
416             (?![>])
417             //xs)
418 0         0 { $out .= "$tag$bracks";
419 0         0 next;
420             }
421              
422 27         62 my $container = $1;
423 27 100       121 if($tag =~ m/[XZ]/) { ; } # ignore container content
    100          
    100          
    50          
    50          
    0          
424             elsif($tag =~ m/[BCI]/) # cannot display, but can be nested
425 13         39 { $out .= $self->_removeMarkup($container);
426             }
427 3         11 elsif($tag eq 'E') { $out .= e2char($container) }
428 0         0 elsif($tag eq 'F') { $out .= $container }
429             elsif($tag eq 'L')
430 8 100       27 { if($container =~ m!^\s*([^/|]*)\|!)
431 4         11 { $out .= $self->_removeMarkup($1);
432 4         14 next;
433             }
434            
435 4         8 my ($man, $chapter) = ($container, '');
436 4 100       20 if($container =~ m!^\s*([^/]*)/\"([^"]*)\"\s*$!)
    100          
437 2         6 { ($man, $chapter) = ($1, $2);
438             }
439             elsif($container =~ m!^\s*([^/]*)/(.*?)\s*$!)
440 1         3 { ($man, $chapter) = ($1, $2);
441             }
442              
443             $out .=
444 4 100       23 ( !length $man ? "section $chapter"
    100          
445             : !length $chapter ? $man
446             : "$man section $chapter"
447             );
448             }
449             elsif($tag eq 'S')
450 0         0 { my $clean = $self->_removeMarkup($container);
451 0         0 $clean =~ s/ /[NB]/g;
452 0         0 $out .= $clean;
453             }
454             }
455              
456 37         123 $out . $string;
457             }
458              
459             sub showSubroutineDescription(@)
460 0     0 1   { my ($self, %args) = @_;
461 0 0         my $manual = $args{manual} or panic;
462 0 0         my $subroutine = $args{subroutine} or panic;
463              
464 0           my $text = $self->cleanup($manual, $subroutine->description);
465 0 0         return $self unless length $text;
466              
467 0 0         my $output = $args{output} or panic;
468 0           $output->print("\n", $text);
469              
470 0 0         my $extends = $self->extends or return $self;
471 0 0         my $refer = $extends->findDescriptionObject or return $self;
472 0           $self->showSubroutineDescriptionRefer(%args, subroutine => $refer);
473             }
474              
475             sub showSubroutineDescriptionRefer(@)
476 0     0 0   { my ($self, %args) = @_;
477 0 0         my $manual = $args{manual} or panic;
478 0 0         my $subroutine = $args{subroutine} or panic;
479 0 0         my $output = $args{output} or panic;
480 0           $output->print("\nInherited, see ",$self->link($manual, $subroutine),"\n");
481             }
482              
483       0 0   sub showSubsIndex() {;}
484              
485              
486             sub cleanupPOD($$)
487 0     0 1   { my ($self, $infn, $outfn) = @_;
488 0 0         my $in = IO::File->new($infn, 'r')
489             or fault __x"cannot read prelimary pod from {file}", file => $infn;
490              
491 0 0         my $out = IO::File->new($outfn, 'w')
492             or fault __x"cannot write final pod to {file}", file => $outfn;
493              
494 0           my $last_is_blank = 1;
495             LINE:
496 0           while(my $l = $in->getline)
497 0 0         { if($l =~ m/^\s*$/s)
498 0 0         { next LINE if $last_is_blank;
499 0           $last_is_blank = 1;
500             }
501             else
502 0           { $last_is_blank = 0;
503             }
504              
505 0           $out->print($l);
506             }
507              
508 0           $in->close;
509 0 0         $out->close
510             or fault __x"write to {file} failed", file => $outfn;
511              
512 0           $self;
513             }
514              
515              
516             1;