File Coverage

lib/OODoc/Format.pm
Criterion Covered Total %
statement 18 206 8.7
branch 0 134 0.0
condition 0 85 0.0
subroutine 6 48 12.5
pod 28 40 70.0
total 52 513 10.1


line stmt bran cond sub pod time code
1             # This code is part of Perl distribution OODoc version 3.05.
2             # The POD got stripped from this file by OODoc version 3.05.
3             # For contributors see file ChangeLog.
4              
5             # This software is copyright (c) 2003-2025 by Mark Overmeer.
6              
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
10              
11              
12             package OODoc::Format;{
13             our $VERSION = '3.05';
14             }
15              
16 2     2   2550 use parent 'OODoc::Object';
  2         4  
  2         15  
17              
18 2     2   150 use strict;
  2         3  
  2         43  
19 2     2   7 use warnings;
  2         3  
  2         111  
20              
21 2     2   8 use Log::Report 'oodoc';
  2         3  
  2         11  
22              
23 2     2   1526 use OODoc::Manifest ();
  2         6  
  2         65  
24 2     2   15 use Scalar::Util qw/weaken/;
  2         3  
  2         6364  
25              
26             our %formatters = (
27             pod => 'OODoc::Format::Pod',
28             pod2 => 'OODoc::Format::Pod2',
29             pod3 => 'OODoc::Format::Pod3',
30             html => 'OODoc::Format::Html',
31             html2 => 'OODoc::Format::Html2', # not (yet) included in the OODoc release
32             );
33              
34             #--------------------
35              
36             sub new($%)
37 0     0 1   { my ($class, %args) = @_;
38              
39 0 0         $class eq __PACKAGE__
40             or return $class->SUPER::new(%args);
41              
42 0 0         my $format = $args{format} or error __x"no formatter specified";
43 0   0       my $pkg = $formatters{$format} || $format;
44              
45 0           eval "require $pkg";
46 0 0         $@ and error __x"formatter {name} has compilation errors: {err}", name => $format, err => $@;
47              
48 0           $pkg->new(%args);
49             }
50              
51             sub init($)
52 0     0 0   { my ($self, $args) = @_;
53              
54 0 0         $self->SUPER::init($args) or return;
55 0           $self->{OF_format} = delete $args->{format};
56              
57             my $name = $self->{OF_project} = delete $args->{project}
58 0 0         or error __x"formatter knows no project name";
59              
60             $self->{OF_version} = delete $args->{version}
61 0 0         or error __x"formatter for {name} does not know the version", name => $name;
62              
63             $self->{OF_workdir} = delete $args->{workdir}
64 0 0         or error __x"no working directory specified for {name}", name => $name;
65              
66 0   0       $self->{OF_manifest} = delete $args->{manifest} || OODoc::Manifest->new;
67              
68 0 0         $self->{OF_index} = delete $args->{index} or error __x"no index specified";
69 0           weaken($self->{OF_index});
70              
71 0           $self;
72             }
73              
74 0     0 1   sub publish { panic }
75              
76             #--------------------
77              
78 0     0 1   sub project() { $_[0]->{OF_project} }
79              
80              
81 0     0 1   sub version() { $_[0]->{OF_version} }
82 0     0 1   sub workdir() { $_[0]->{OF_workdir} }
83 0     0 1   sub manifest() { $_[0]->{OF_manifest} }
84 0     0 1   sub format() { $_[0]->{OF_format} }
85 0     0 1   sub index() { $_[0]->{OF_index} }
86              
87             #--------------------
88              
89             sub createPages(%)
90 0     0 1   { my ($self, %args) = @_;
91              
92 0   0 0     my $sel = $args{select} || sub { 1 };
  0            
93 0 0   0     my $select = ref $sel eq 'CODE' ? $sel : sub { $_[0]->name =~ $sel };
  0            
94              
95             # Manual knowledge is global
96              
97 0   0       my $options = $args{manual_format} || [];
98 0           my $index = $self->index;
99              
100 0           foreach my $package (sort $index->packageNames)
101             {
102 0           foreach my $manual ($index->manualsForPackage($package))
103 0 0         { $select->($manual) or next;
104              
105 0 0         unless($manual->chapters)
106 0           { trace " skipping $manual: no chapters";
107 0           next;
108             }
109              
110 0           trace " creating manual $manual with ".(ref $self);
111              
112             $self->createManual(
113             manual => $manual,
114             template => $args{manual_templates},
115             append => $args{append},
116 0           @$options
117             );
118             }
119             }
120              
121             #
122             # Create other pages
123             #
124              
125 0           trace "creating other pages";
126 0           $self->createOtherPages(source => $args{other_templates}, process => $args{process_files});
127              
128 0           1;
129             }
130              
131              
132 0     0 1   sub createManual(@) {panic}
133              
134              
135 0     0 1   sub cleanup($$%) { ... }
136              
137              
138 0     0 1   sub cleanupString($$%) { shift->cleanup(@_) }
139              
140              
141             sub showChapter(@)
142 0     0 1   { my ($self, %args) = @_;
143 0 0         my $chapter = $args{chapter} or panic;
144 0 0         my $manual = $args{manual} or panic;
145              
146 0           my $show_inh = $args{show_inherited};
147 0   0       my $show_ch = $args{show_inherited_chapter} || $show_inh;
148 0   0       my $show_sec = $args{show_inherited_section} || $show_inh;
149 0   0       my $show_ssec = $args{show_inherited_subsection} || $show_inh;
150 0   0       my $show_sssec = $args{show_inherited_subsubsection} || $show_inh;
151              
152 0   0       my $show_examples = $args{show_examples} || 'EXPAND';
153              
154 0 0         if($manual->inherited($chapter))
155 0 0         { return $self if $show_ch eq 'NO';
156 0           $self->showStructureRefer(%args, structure => $chapter);
157 0           return $self;
158             }
159              
160             $self->showStructureExpanded(%args, structure => $chapter,
161 0   0       show_examples => $args{show_chapter_examples} || $show_examples,
162             );
163              
164 0           foreach my $section ($chapter->sections)
165 0 0         { if($manual->inherited($section))
166 0 0         { next if $show_sec eq 'NO';
167 0 0         if($show_sec ne 'REFER')
168 0           { $self->showStructureRefer(%args, structure => $section);
169 0           next;
170             }
171             }
172              
173             $self->showStructureExpanded(%args, structure => $section,
174 0   0       show_examples => $args{show_section_examples} || $show_examples,
175             );
176              
177 0           foreach my $subsection ($section->subsections)
178 0 0         { if($manual->inherited($subsection))
179 0 0         { next if $show_ssec eq 'NO';
180 0 0         if($show_ssec ne 'REFER')
181 0           { $self->showStructureRefer(%args, structure => $subsection);
182 0           next;
183             }
184             }
185              
186             $self->showStructureExpanded(%args, structure => $subsection,
187 0   0       show_examples => $args{show_subsection_examples} || $show_examples,
188             );
189              
190 0           foreach my $subsubsection ($subsection->subsubsections)
191 0 0         { if($manual->inherited($subsubsection))
192 0 0         { next if $show_sssec eq 'NO';
193 0 0         if($show_sssec ne 'REFER')
194 0           { $self->showStructureRefer(%args, structure => $subsubsection);
195 0           next;
196             }
197             }
198              
199             $self->showStructureExpanded(%args, structure => $subsubsection,
200 0   0       show_examples => $args{show_subsubsection_examples} || $show_examples,
201             );
202             }
203             }
204             }
205             }
206              
207              
208 0     0 1   sub showStructureExpanded(@) {panic}
209              
210              
211 0     0 1   sub showStructureRefer(@) {panic}
212              
213 0     0 0   sub chapterName(@) { $_[0]->showRequiredChapter(NAME => @_) }
214 0     0 0   sub chapterSynopsis(@) { $_[0]->showOptionalChapter(SYNOPSIS => @_) }
215 0     0 0   sub chapterInheritance(@) { $_[0]->showOptionalChapter(INHERITANCE => @_) }
216 0     0 0   sub chapterDescription(@) { $_[0]->showRequiredChapter(DESCRIPTION => @_) }
217 0     0 0   sub chapterOverloaded(@) { $_[0]->showOptionalChapter(OVERLOADED => @_) }
218 0     0 0   sub chapterMethods(@) { $_[0]->showOptionalChapter(METHODS => @_) }
219 0     0 0   sub chapterExports(@) { $_[0]->showOptionalChapter(EXPORTS => @_) }
220 0     0 0   sub chapterDiagnostics(@) { $_[0]->showOptionalChapter(DIAGNOSTICS => @_) }
221 0     0 0   sub chapterDetails(@) { $_[0]->showOptionalChapter(DETAILS => @_) }
222 0     0 0   sub chapterReferences(@) { $_[0]->showOptionalChapter(REFERENCES => @_) }
223 0     0 0   sub chapterCopyrights(@) { $_[0]->showOptionalChapter(COPYRIGHTS => @_) }
224              
225              
226             sub showRequiredChapter($%)
227 0     0 1   { my ($self, $name, %args) = @_;
228 0 0         my $manual = $args{manual} or panic;
229              
230 0 0         my $chapter = $manual->chapter($name)
231             or (error __x"missing required chapter {name} in {manual}", name => $name, manual => $manual), return;
232              
233 0           $self->showChapter(chapter => $chapter, %args);
234             }
235              
236              
237             sub showOptionalChapter($@)
238 0     0 1   { my ($self, $name, %args) = @_;
239 0 0         my $manual = $args{manual} or panic;
240 0 0         my $chapter = $manual->chapter($name) or return;
241 0           $self->showChapter(chapter => $chapter, %args);
242             }
243              
244              
245 0     0 1   sub createOtherPages(@) { $_[0] }
246              
247              
248             sub showSubroutines(@)
249 0     0 1   { my ($self, %args) = @_;
250              
251 0 0         my @subs = $args{subroutines} ? sort @{$args{subroutines}} : [];
  0            
252 0 0         @subs or return $self;
253              
254 0 0         my $manual = $args{manual} or panic;
255 0   0       my $output = $args{output} || select;
256              
257             # list is also in ::Pod3
258 0   0       $args{show_described_options} ||= 'EXPAND';
259 0   0       $args{show_described_subs} ||= 'EXPAND';
260 0   0       $args{show_diagnostics} ||= 'NO';
261 0   0       $args{show_examples} ||= 'EXPAND';
262 0   0       $args{show_inherited_options} ||= 'USE';
263 0   0       $args{show_inherited_subs} ||= 'USE';
264 0   0       $args{show_option_table} ||= 'ALL';
265 0   0       $args{show_subs_index} ||= 'NO';
266              
267 0           $self->showSubsIndex(%args, subroutines => \@subs);
268              
269 0           for(my $index=0; $index<@subs; $index++)
270 0           { my $subroutine = $subs[$index];
271 0 0         my $show = $manual->inherited($subroutine) ? $args{show_inherited_subs} : $args{show_described_subs};
272              
273 0           $self->showSubroutine(
274             %args,
275             subroutine => $subroutine,
276             show_subroutine => $show,
277             last => ($index==$#subs),
278             );
279             }
280             }
281              
282              
283             sub showSubroutine(@)
284 0     0 1   { my ($self, %args) = @_;
285              
286 0 0         my $subroutine = $args{subroutine} or panic;
287 0 0         my $manual = $args{manual} or panic;
288 0   0       my $output = $args{output} || select;
289              
290             #
291             # Method use
292             #
293              
294 0   0       my $use = $args{show_subroutine} || 'EXPAND';
295 0 0         my ($show_use, $expand)
    0          
    0          
    0          
296             = $use eq 'EXPAND' ? ('showSubroutineUse', 1)
297             : $use eq 'USE' ? ('showSubroutineUse', 0)
298             : $use eq 'NAMES' ? ('showSubroutineName', 0)
299             : $use eq 'NO' ? (undef, 0)
300             : error __x"illegal value for show_subroutine: {value}", value => $use;
301              
302 0 0         $self->$show_use(%args, subroutine => $subroutine)
303             if defined $show_use;
304              
305 0 0         $expand or return;
306              
307 0   0       $args{show_inherited_options} ||= 'USE';
308 0   0       $args{show_described_options} ||= 'EXPAND';
309              
310             #
311             # Subroutine descriptions
312             #
313              
314 0   0       my $descr = $args{show_sub_description} || 'DESCRIBED';
315 0           my $description = $subroutine->findDescriptionObject;
316 0           my $show_descr = 'showSubroutineDescription';
317              
318 0 0         if($descr eq 'NO') { $show_descr = undef }
  0 0          
    0          
    0          
319             elsif($descr eq 'REFER')
320 0 0 0       { $show_descr = 'showSubroutineDescriptionRefer'
321             if $description && $manual->inherited($description);
322             }
323             elsif($descr eq 'DESCRIBED')
324 0 0 0       { $show_descr = 'showSubroutineDescriptionRefer'
325             if $description && $manual->inherited($description);
326             }
327             elsif($descr eq 'ALL') {;}
328 0           else { error __x"illegal value for show_sub_description: {value}", value => $descr}
329              
330 0 0 0       $self->$show_descr(%args, subroutine => $description // $subroutine)
331             if defined $show_descr;
332              
333             #
334             # Options
335             #
336              
337 0           my $options = $subroutine->collectedOptions;
338              
339 0   0       my $opttab = $args{show_option_table} || 'NAMES';
340 0           my @options = @{$options}{ sort keys %$options };
  0            
341              
342             # Option table
343              
344             my @opttab
345 0 0         = $opttab eq 'NO' ? ()
    0          
    0          
    0          
346             : $opttab eq 'DESCRIBED'? (grep not $manual->inherits($_->[0]), @options)
347             : $opttab eq 'INHERITED'? (grep $manual->inherits($_->[0]), @options)
348             : $opttab eq 'ALL' ? @options
349             : error __x"illegal value for show_option_table: {value}", value => $opttab;
350              
351 0 0         $self->showOptionTable(%args, options => \@opttab) if @opttab;
352              
353             # Option expanded
354              
355 0           my @optlist;
356 0           foreach (@options)
357 0           { my ($option, $default) = @$_;
358 0 0         my $check = $manual->inherited($option) ? $args{show_inherited_options} : $args{show_described_options};
359 0 0 0       push @optlist, $_ if $check eq 'USE' || $check eq 'EXPAND';
360             }
361              
362 0 0         $self->showOptions(%args, options => \@optlist)
363             if @optlist;
364              
365             # Examples
366              
367 0           my @examples = $subroutine->examples;
368 0   0       my $show_ex = $args{show_examples} || 'EXPAND';
369 0 0         $self->showExamples(%args, examples => \@examples)
370             if $show_ex eq 'EXPAND';
371              
372             # Diagnostics
373              
374 0           my @diags = $subroutine->diagnostics;
375 0   0       my $show_diag= $args{show_diagnostics} || 'NO';
376 0 0         $self->showDiagnostics(%args, diagnostics => \@diags)
377             if $show_diag eq 'EXPAND';
378             }
379              
380              
381 0     0 1   sub showExamples(@) { $_[0] }
382              
383              
384 0     0 1   sub showSubroutineUse(@) { $_[0] }
385              
386              
387 0     0 1   sub showSubroutineName(@) { $_[0] }
388              
389              
390 0     0 1   sub showSubroutineDescription(@) { $_[0] }
391              
392              
393             sub showOptionTable(@)
394 0     0 1   { my ($self, %args) = @_;
395 0 0         my $options = $args{options} or panic;
396 0 0         my $manual = $args{manual} or panic;
397 0 0         my $output = $args{output} or panic;
398              
399 0           my @rows;
400 0           foreach (@$options)
401 0           { my ($option, $default) = @$_;
402 0           my $optman = $option->manual;
403 0 0         push @rows, [
404             $self->cleanupString($manual, $option->name, tag => 'option_name'),
405             ($manual->inherited($option) ? $self->link(undef, $optman) : ''),
406             $self->cleanupString($manual, $default->value, tag => 'option_default'),
407             ];
408             }
409              
410 0           my @header = ('Option', 'Defined in', 'Default');
411 0 0         unless(grep length $_->[1], @rows)
412             { # removed empty "defined in" column
413 0           splice @$_, 1, 1 for @rows, \@header;
414             }
415              
416 0           $output->print("\n");
417 0           $self->writeTable(output => $output, header => \@header, rows => \@rows, widths => [undef, 15, undef]);
418 0           $self;
419             }
420              
421              
422             sub showOptions(@)
423 0     0 1   { my ($self, %args) = @_;
424              
425 0 0         my $options = $args{options} or panic;
426 0 0         my $manual = $args{manual} or panic;
427              
428 0           foreach (@$options)
429 0           { my ($option, $default) = @$_;
430 0 0         my $show = $manual->inherited($option) ? $args{show_inherited_options} : $args{show_described_options};
431              
432 0 0         my $action
    0          
433             = $show eq 'USE' ? 'showOptionUse'
434             : $show eq 'EXPAND'? 'showOptionExpand'
435             : error __x"illegal show option choice: {value}", value => $show;
436              
437 0           $self->$action(%args, option => $option, default => $default);
438             }
439 0           $self;
440             }
441              
442              
443 0     0 1   sub showOptionUse(@) { $_[0] }
444              
445              
446 0     0 1   sub showOptionExpand(@) { $_[0] }
447              
448             1;