File Coverage

lib/OODoc/Format/Pod.pm
Criterion Covered Total %
statement 51 287 17.7
branch 19 196 9.6
condition 0 12 0.0
subroutine 10 34 29.4
pod 17 25 68.0
total 97 554 17.5


line stmt bran cond sub pod time code
1             # Copyrights 2003-2013 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.00.
5             package OODoc::Format::Pod;
6 2     2   27737 use vars '$VERSION';
  2         4  
  2         131  
7             $VERSION = '2.00';
8              
9 2     2   12 use base 'OODoc::Format';
  2         3  
  2         676  
10              
11 2     2   12 use strict;
  2         4  
  2         59  
12 2     2   12 use warnings;
  2         3  
  2         57  
13              
14 2     2   8 use Log::Report 'oodoc';
  2         11  
  2         16  
15              
16 2     2   594 use File::Spec ();
  2         5  
  2         42  
17 2     2   9 use List::Util qw/max/;
  2         4  
  2         134  
18 2     2   1875 use Pod::Escapes qw/e2char/;
  2         7832  
  2         8599  
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 0         0 $self->formatManual
58             ( manual => $manual
59             , output => $output
60             , append => $args{append}
61             , @$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("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 = length $paramlist ? "($paramlist)" : '()';
271              
272 0         0 my $class = $manual->package;
273 0 0       0 my $use
    0          
    0          
    0          
    0          
    0          
274             = $type eq 'i_method' ? qq[\$obj-EB<$name>$params]
275             : $type eq 'c_method' ? qq[$class-EB<$name>$params]
276             : $type eq 'ci_method'? qq[\$obj-EB<$name>$params\n]
277             . qq[$class-EB<$name>$params]
278             : $type eq 'function' ? qq[B<$name>$params]
279             : $type eq 'overload' ? qq[overload: B<$name>$params]
280             : $type eq 'tie' ? qq[B<$name>$params]
281             : '';
282              
283 0 0       0 length $use
284             or warn "WARNING: unknown subroutine type $type for $name in $manual";
285              
286 0         0 $use;
287             }
288              
289             sub showSubroutineName(@)
290 0     0 1 0 { my ($self, %args) = @_;
291 0 0       0 my $subroutine = $args{subroutine} or panic;
292 0 0       0 my $manual = $args{manual} or panic;
293 0 0       0 my $output = $args{output} or panic;
294 0         0 my $name = $subroutine->name;
295              
296 0 0       0 my $url
297             = $manual->inherited($subroutine)
298             ? "M<".$subroutine->manual."::$name>"
299             : "M<$name>";
300              
301 0 0       0 $output->print
302             ( $self->cleanup($manual, $url)
303             , ($args{last} ? ".\n" : ",\n")
304             );
305             }
306              
307             sub showOptions(@)
308 0     0 1 0 { my ($self, %args) = @_;
309 0 0       0 my $output = $args{output} or panic;
310 0         0 $output->print("\n=over 2\n\n");
311 0         0 $self->SUPER::showOptions(%args);
312 0         0 $output->print("\n=back\n\n");
313             }
314              
315             sub showOptionUse(@)
316 0     0 1 0 { my ($self, %args) = @_;
317 0 0       0 my $output = $args{output} or panic;
318 0 0       0 my $option = $args{option} or panic;
319 0 0       0 my $manual = $args{manual} or panic;
320              
321 0         0 my $params = $option->parameters;
322 0         0 $params =~ s/\s+$//;
323 0         0 $params =~ s/^\s+//;
324 0 0       0 $params = " => ".$self->cleanup($manual, $params) if length $params;
325            
326 0         0 $output->print("=item $option$params\n\n");
327 0         0 $self;
328             }
329              
330             sub showOptionExpand(@)
331 0     0 1 0 { my ($self, %args) = @_;
332 0 0       0 my $output = $args{output} or panic;
333 0 0       0 my $option = $args{option} or panic;
334 0 0       0 my $manual = $args{manual} or panic;
335              
336 0         0 $self->showOptionUse(%args);
337              
338 0 0       0 my $where = $option->findDescriptionObject or return $self;
339 0         0 my $descr = $self->cleanup($manual, $where->description);
340 0 0       0 $output->print("\n$descr\n\n")
341             if length $descr;
342              
343 0         0 $self;
344             }
345              
346              
347             sub writeTable($@)
348 0     0 1 0 { my ($self, %args) = @_;
349              
350 0 0       0 my $head = $args{header} or panic;
351 0 0       0 my $output = $args{output} or panic;
352 0 0       0 my $rows = $args{rows} or panic;
353 0 0       0 return unless @$rows;
354              
355             # Convert all elements to plain text, because markup is not
356             # allowed in verbatim pod blocks.
357 0         0 my @rows;
358 0         0 foreach my $row (@$rows)
359 0         0 { push @rows, [ map {$self->removeMarkup($_)} @$row ];
  0         0  
360             }
361              
362             # Compute column widths
363 0         0 my @w = (0) x @$head;
364              
365 0         0 foreach my $row ($head, @rows)
366             { $w[$_] = max $w[$_], length($row->[$_])
367 0         0 foreach 0..$#$row;
368             }
369              
370 0 0       0 if(my $widths = $args{widths})
371             { defined $widths->[$_] && $widths->[$_] > $w[$_] && ($w[$_] = $widths->[$_])
372 0   0     0 for 0..$#$rows;
      0        
373             }
374              
375 0         0 pop @w; # ignore width of last column
376              
377             # Table head
378 0         0 my $headf = " -".join("--", map { "\%-${_}s" } @w)."--%s\n";
  0         0  
379 0         0 $output->printf($headf, @$head);
380              
381             # Table body
382 0         0 my $format = " ".join(" ", map { "\%-${_}s" } @w)." %s\n";
  0         0  
383             $output->printf($format, @$_)
384 0         0 for @rows;
385             }
386              
387              
388             sub removeMarkup($)
389 20     20 1 53 { my ($self, $string) = @_;
390 20         44 my $out = $self->_removeMarkup($string);
391 20         188 for($out)
392 20         43 { s/^\s+//gm;
393 20         45 s/\s+$//gm;
394 20         38 s/\s{2,}/ /g;
395 20         43 s/\[NB\]/ /g;
396             }
397 20         101 $out;
398             }
399              
400             sub _removeMarkup($)
401 37     37   58 { my ($self, $string) = @_;
402              
403 37         43 my $out = '';
404 37         147 while($string =~ s/(.*?) # before
405             ([BCEFILSXZ]) # known formatting codes
406             ([<]+) # capture ALL starters
407             //x)
408 27         81 { $out .= $1;
409 27         71 my ($tag, $bracks, $brack_count) = ($2, $3, length($3));
410              
411 27 50       475 if($string !~ s/^(|.*?[^>]) # contained
412             [>]{$brack_count}
413             (?![>])
414             //xs)
415 0         0 { $out .= "$tag$bracks";
416 0         0 next;
417             }
418              
419 27         61 my $container = $1;
420 27 100       109 if($tag =~ m/[XZ]/) { ; } # ignore container content
    100          
    100          
    50          
    50          
    0          
421             elsif($tag =~ m/[BCI]/) # cannot display, but can be nested
422 13         40 { $out .= $self->_removeMarkup($container);
423             }
424 3         12 elsif($tag eq 'E') { $out .= e2char($container) }
425 0         0 elsif($tag eq 'F') { $out .= $container }
426             elsif($tag eq 'L')
427 8 100       30 { if($container =~ m!^\s*([^/|]*)\|!)
428 4         11 { $out .= $self->_removeMarkup($1);
429 4         14 next;
430             }
431            
432 4         7 my ($man, $chapter) = ($container, '');
433 4 100       23 if($container =~ m!^\s*([^/]*)/\"([^"]*)\"\s*$!)
    100          
434 2         6 { ($man, $chapter) = ($1, $2);
435             }
436             elsif($container =~ m!^\s*([^/]*)/(.*?)\s*$!)
437 1         3 { ($man, $chapter) = ($1, $2);
438             }
439              
440             $out .=
441 4 100       24 ( !length $man ? "section $chapter"
    100          
442             : !length $chapter ? $man
443             : "$man section $chapter"
444             );
445             }
446             elsif($tag eq 'S')
447 0         0 { my $clean = $self->_removeMarkup($container);
448 0         0 $clean =~ s/ /[NB]/g;
449 0         0 $out .= $clean;
450             }
451             }
452              
453 37         119 $out . $string;
454             }
455              
456             sub showSubroutineDescription(@)
457 0     0 1   { my ($self, %args) = @_;
458 0 0         my $manual = $args{manual} or panic;
459 0 0         my $subroutine = $args{subroutine} or panic;
460              
461 0           my $text = $self->cleanup($manual, $subroutine->description);
462 0 0         return $self unless length $text;
463              
464 0 0         my $output = $args{output} or panic;
465 0           $output->print("\n", $text);
466              
467 0 0         my $extends = $self->extends or return $self;
468 0 0         my $refer = $extends->findDescriptionObject or return $self;
469 0           $self->showSubroutineDescriptionRefer(%args, subroutine => $refer);
470             }
471              
472             sub showSubroutineDescriptionRefer(@)
473 0     0 0   { my ($self, %args) = @_;
474 0 0         my $manual = $args{manual} or panic;
475 0 0         my $subroutine = $args{subroutine} or panic;
476 0 0         my $output = $args{output} or panic;
477 0           $output->print("\nSee ", $self->link($manual, $subroutine), "\n");
478             }
479              
480 0     0 0   sub showSubsIndex() {;}
481              
482              
483             sub cleanupPOD($$)
484 0     0 1   { my ($self, $infn, $outfn) = @_;
485 0 0         my $in = IO::File->new($infn, 'r')
486             or fault __x"cannot read prelimary pod from {file}", file => $infn;
487              
488 0 0         my $out = IO::File->new($outfn, 'w')
489             or fault __x"cannot write final pod to {file}", file => $outfn;
490              
491 0           my $last_is_blank = 1;
492             LINE:
493 0           while(my $l = $in->getline)
494 0 0         { if($l =~ m/^\s*$/s)
495 0 0         { next LINE if $last_is_blank;
496 0           $last_is_blank = 1;
497             }
498             else
499 0           { $last_is_blank = 0;
500             }
501              
502 0           $out->print($l);
503             }
504              
505 0           $in->close;
506 0 0         $out->close
507             or fault __x"write to {file} failed", file => $outfn;
508              
509 0           $self;
510             }
511              
512              
513             1;