File Coverage

blib/lib/Pod/Text.pm
Criterion Covered Total %
statement 310 342 90.6
branch 108 144 75.0
condition 37 49 75.5
subroutine 57 58 98.2
pod 6 46 13.0
total 518 639 81.0


line stmt bran cond sub pod time code
1             # Convert POD data to formatted text.
2             #
3             # This module converts POD to formatted text. It replaces the old Pod::Text
4             # module that came with versions of Perl prior to 5.6.0 and attempts to match
5             # its output except for some specific circumstances where other decisions
6             # seemed to produce better output. It uses Pod::Parser and is designed to be
7             # very easy to subclass.
8             #
9             # Perl core hackers, please note that this module is also separately
10             # maintained outside of the Perl core as part of the podlators. Please send
11             # me any patches at the address above in addition to sending them to the
12             # standard Perl mailing lists.
13             #
14             # Copyright 1999, 2000, 2001, 2002, 2004, 2006, 2008, 2009, 2012, 2013, 2014,
15             # 2015, 2016 Russ Allbery
16             #
17             # This program is free software; you may redistribute it and/or modify it
18             # under the same terms as Perl itself.
19              
20             ##############################################################################
21             # Modules and declarations
22             ##############################################################################
23              
24             package Pod::Text;
25              
26 12     12   351099 use 5.006;
  12         93  
27 12     12   55 use strict;
  12         41  
  12         276  
28 12     12   66 use warnings;
  12         16  
  12         343  
29              
30 12     12   56 use vars qw(@ISA @EXPORT %ESCAPES $VERSION);
  12         16  
  12         691  
31              
32 12     12   55 use Carp qw(carp croak);
  12         21  
  12         577  
33 12     12   4182 use Encode qw(encode);
  12         73622  
  12         569  
34 12     12   63 use Exporter ();
  12         19  
  12         162  
35 12     12   4061 use Pod::Simple ();
  12         195227  
  12         43406  
36              
37             @ISA = qw(Pod::Simple Exporter);
38              
39             # We have to export pod2text for backward compatibility.
40             @EXPORT = qw(pod2text);
41              
42             $VERSION = '4.10';
43              
44             # Ensure that $Pod::Simple::nbsp and $Pod::Simple::shy are available. Code
45             # taken from Pod::Simple 3.32, but was only added in 3.30.
46             my ($NBSP, $SHY);
47             if ($Pod::Simple::VERSION ge 3.30) {
48             $NBSP = $Pod::Simple::nbsp;
49             $SHY = $Pod::Simple::shy;
50             } else {
51             if ($] ge 5.007_003) {
52             $NBSP = chr utf8::unicode_to_native(0xA0);
53             $SHY = chr utf8::unicode_to_native(0xAD);
54             } elsif (Pod::Simple::ASCII) {
55             $NBSP = "\xA0";
56             $SHY = "\xAD";
57             } else {
58             $NBSP = "\x41";
59             $SHY = "\xCA";
60             }
61             }
62              
63             ##############################################################################
64             # Initialization
65             ##############################################################################
66              
67             # This function handles code blocks. It's registered as a callback to
68             # Pod::Simple and therefore doesn't work as a regular method call, but all it
69             # does is call output_code with the line.
70             sub handle_code {
71 8     8 0 150 my ($line, $number, $parser) = @_;
72 8         16 $parser->output_code ($line . "\n");
73             }
74              
75             # Initialize the object and set various Pod::Simple options that we need.
76             # Here, we also process any additional options passed to the constructor or
77             # set up defaults if none were given. Note that all internal object keys are
78             # in all-caps, reserving all lower-case object keys for Pod::Simple and user
79             # arguments.
80             sub new {
81 29     29 1 24422 my $class = shift;
82 29         131 my $self = $class->SUPER::new;
83              
84             # Tell Pod::Simple to handle S<> by automatically inserting  .
85 29         626 $self->nbsp_for_S (1);
86              
87             # Tell Pod::Simple to keep whitespace whenever possible.
88 29 50       390 if ($self->can ('preserve_whitespace')) {
89 29         67 $self->preserve_whitespace (1);
90             } else {
91 0         0 $self->fullstop_space_harden (1);
92             }
93              
94             # The =for and =begin targets that we accept.
95 29         270 $self->accept_targets (qw/text TEXT/);
96              
97             # Ensure that contiguous blocks of code are merged together. Otherwise,
98             # some of the guesswork heuristics don't work right.
99 29         610 $self->merge_text (1);
100              
101             # Pod::Simple doesn't do anything useful with our arguments, but we want
102             # to put them in our object as hash keys and values. This could cause
103             # problems if we ever clash with Pod::Simple's own internal class
104             # variables.
105 29         145 my %opts = @_;
106 29         62 my @opts = map { ("opt_$_", $opts{$_}) } keys %opts;
  16         54  
107 29         142 %$self = (%$self, @opts);
108              
109             # Send errors to stderr if requested.
110 29 100 66     101 if ($$self{opt_stderr} and not $$self{opt_errors}) {
111 1         3 $$self{opt_errors} = 'stderr';
112             }
113 29         40 delete $$self{opt_stderr};
114              
115             # Validate the errors parameter and act on it.
116 29 100       69 if (not defined $$self{opt_errors}) {
117 24         51 $$self{opt_errors} = 'pod';
118             }
119 29 100 100     169 if ($$self{opt_errors} eq 'stderr' || $$self{opt_errors} eq 'die') {
    100          
    50          
120 3         8 $self->no_errata_section (1);
121 3         17 $self->complain_stderr (1);
122 3 100       14 if ($$self{opt_errors} eq 'die') {
123 1         2 $$self{complain_die} = 1;
124             }
125             } elsif ($$self{opt_errors} eq 'pod') {
126 25         97 $self->no_errata_section (0);
127 25         172 $self->complain_stderr (0);
128             } elsif ($$self{opt_errors} eq 'none') {
129 1         7 $self->no_whining (1);
130             } else {
131 0         0 croak (qq(Invalid errors setting: "$$self{errors}"));
132             }
133 29         121 delete $$self{errors};
134              
135             # Initialize various things from our parameters.
136 29 100       74 $$self{opt_alt} = 0 unless defined $$self{opt_alt};
137 29 50       70 $$self{opt_indent} = 4 unless defined $$self{opt_indent};
138 29 100       71 $$self{opt_margin} = 0 unless defined $$self{opt_margin};
139 29 50       61 $$self{opt_loose} = 0 unless defined $$self{opt_loose};
140 29 100       58 $$self{opt_sentence} = 0 unless defined $$self{opt_sentence};
141 29 50       63 $$self{opt_width} = 76 unless defined $$self{opt_width};
142              
143             # Figure out what quotes we'll be using for C<> text.
144 29   100     132 $$self{opt_quotes} ||= '"';
145 29 50       83 if ($$self{opt_quotes} eq 'none') {
    100          
    50          
146 0         0 $$self{LQUOTE} = $$self{RQUOTE} = '';
147             } elsif (length ($$self{opt_quotes}) == 1) {
148 28         61 $$self{LQUOTE} = $$self{RQUOTE} = $$self{opt_quotes};
149             } elsif (length ($$self{opt_quotes}) % 2 == 0) {
150 1         3 my $length = length ($$self{opt_quotes}) / 2;
151 1         3 $$self{LQUOTE} = substr ($$self{opt_quotes}, 0, $length);
152 1         3 $$self{RQUOTE} = substr ($$self{opt_quotes}, $length);
153             } else {
154 0         0 croak qq(Invalid quote specification "$$self{opt_quotes}");
155             }
156              
157             # If requested, do something with the non-POD text.
158 29 100       63 $self->code_handler (\&handle_code) if $$self{opt_code};
159              
160             # Return the created object.
161 29         105 return $self;
162             }
163              
164             ##############################################################################
165             # Core parsing
166             ##############################################################################
167              
168             # This is the glue that connects the code below with Pod::Simple itself. The
169             # goal is to convert the event stream coming from the POD parser into method
170             # calls to handlers once the complete content of a tag has been seen. Each
171             # paragraph or POD command will have textual content associated with it, and
172             # as soon as all of a paragraph or POD command has been seen, that content
173             # will be passed in to the corresponding method for handling that type of
174             # object. The exceptions are handlers for lists, which have opening tag
175             # handlers and closing tag handlers that will be called right away.
176             #
177             # The internal hash key PENDING is used to store the contents of a tag until
178             # all of it has been seen. It holds a stack of open tags, each one
179             # represented by a tuple of the attributes hash for the tag and the contents
180             # of the tag.
181              
182             # Add a block of text to the contents of the current node, formatting it
183             # according to the current formatting instructions as we do.
184             sub _handle_text {
185 1075     1075   7499 my ($self, $text) = @_;
186 1075         1342 my $tag = $$self{PENDING}[-1];
187 1075         2064 $$tag[1] .= $text;
188             }
189              
190             # Given an element name, get the corresponding method name.
191             sub method_for_element {
192 2204     2204 0 2469 my ($self, $element) = @_;
193 2204         2467 $element =~ tr/-/_/;
194 2204         2299 $element =~ tr/A-Z/a-z/;
195 2204         2190 $element =~ tr/_a-z0-9//cd;
196 2204         3121 return $element;
197             }
198              
199             # Handle the start of a new element. If cmd_element is defined, assume that
200             # we need to collect the entire tree for this element before passing it to the
201             # element method, and create a new tree into which we'll collect blocks of
202             # text and nested elements. Otherwise, if start_element is defined, call it.
203             sub _handle_element_start {
204 1102     1102   202773 my ($self, $element, $attrs) = @_;
205 1102         1599 my $method = $self->method_for_element ($element);
206              
207             # If we have a command handler, we need to accumulate the contents of the
208             # tag before calling it.
209 1102 100       3613 if ($self->can ("cmd_$method")) {
    100          
210 994         1120 push (@{ $$self{PENDING} }, [ $attrs, '' ]);
  994         2048  
211             } elsif ($self->can ("start_$method")) {
212 106         161 my $method = 'start_' . $method;
213 106         223 $self->$method ($attrs, '');
214             }
215             }
216              
217             # Handle the end of an element. If we had a cmd_ method for this element,
218             # this is where we pass along the text that we've accumulated. Otherwise, if
219             # we have an end_ method for the element, call that.
220             sub _handle_element_end {
221 1102     1102   9702 my ($self, $element) = @_;
222 1102         1437 my $method = $self->method_for_element ($element);
223              
224             # If we have a command handler, pull off the pending text and pass it to
225             # the handler along with the saved attribute hash.
226 1102 100       2944 if ($self->can ("cmd_$method")) {
    100          
227 994         1026 my $tag = pop @{ $$self{PENDING} };
  994         1273  
228 994         1357 my $method = 'cmd_' . $method;
229 994         1789 my $text = $self->$method (@$tag);
230 994 50       2361 if (defined $text) {
231 994 100       910 if (@{ $$self{PENDING} } > 1) {
  994         1577  
232 344         794 $$self{PENDING}[-1][1] .= $text;
233             } else {
234 650         884 $self->output ($text);
235             }
236             }
237             } elsif ($self->can ("end_$method")) {
238 106         187 my $method = 'end_' . $method;
239 106         206 $self->$method ();
240             }
241             }
242              
243             ##############################################################################
244             # Output formatting
245             ##############################################################################
246              
247             # Wrap a line, indenting by the current left margin. We can't use Text::Wrap
248             # because it plays games with tabs. We can't use formline, even though we'd
249             # really like to, because it screws up non-printing characters. So we have to
250             # do the wrapping ourselves.
251             sub wrap {
252 162     162 0 173 my $self = shift;
253 162         185 local $_ = shift;
254 162         173 my $output = '';
255 162         253 my $spaces = ' ' x $$self{MARGIN};
256 162         207 my $width = $$self{opt_width} - $$self{MARGIN};
257 162         307 while (length > $width) {
258 39 50 33     374 if (s/^([^\n]{0,$width})\s+// || s/^([^\n]{$width})//) {
259 39         151 $output .= $spaces . $1 . "\n";
260             } else {
261 0         0 last;
262             }
263             }
264 162         296 $output .= $spaces . $_;
265 162         646 $output =~ s/\s+$/\n\n/;
266 162         411 return $output;
267             }
268              
269             # Reformat a paragraph of text for the current margin. Takes the text to
270             # reformat and returns the formatted text.
271             sub reformat {
272 465     465 0 522 my $self = shift;
273 465         568 local $_ = shift;
274              
275             # If we're trying to preserve two spaces after sentences, do some munging
276             # to support that. Otherwise, smash all repeated whitespace.
277 465 100       695 if ($$self{opt_sentence}) {
278 1         4 s/ +$//mg;
279 1         3 s/\.\n/. \n/g;
280 1         4 s/\n/ /g;
281 1         3 s/ +/ /g;
282             } else {
283 464         2247 s/\s+/ /g;
284             }
285 465         1084 return $self->wrap ($_);
286             }
287              
288             # Output text to the output device. Replace non-breaking spaces with spaces
289             # and soft hyphens with nothing, and then try to fix the output encoding if
290             # necessary to match the input encoding unless UTF-8 output is forced. This
291             # preserves the traditional pass-through behavior of Pod::Text.
292             sub output {
293 1243     1243 0 1952 my ($self, @text) = @_;
294 1243         1833 my $text = join ('', @text);
295 1243 50       1843 if ($NBSP) {
296 1243         2080 $text =~ s/$NBSP/ /g;
297             }
298 1243 50       1674 if ($SHY) {
299 1243         1477 $text =~ s/$SHY//g;
300             }
301 1243 100       1966 unless ($$self{opt_utf8}) {
302 1223   100     2608 my $encoding = $$self{encoding} || '';
303 1223 100 100     2075 if ($encoding && $encoding ne $$self{ENCODING}) {
304 5         20 $$self{ENCODING} = $encoding;
305 5     1   7 eval { binmode ($$self{output_fh}, ":encoding($encoding)") };
  5         79  
  1         27  
  1         13  
  1         6  
306             }
307             }
308 1243 50       2478 if ($$self{ENCODE}) {
309 0         0 print { $$self{output_fh} } encode ('UTF-8', $text);
  0         0  
310             } else {
311 1243         1124 print { $$self{output_fh} } $text;
  1243         3415  
312             }
313             }
314              
315             # Output a block of code (something that isn't part of the POD text). Called
316             # by preprocess_paragraph only if we were given the code option. Exists here
317             # only so that it can be overridden by subclasses.
318 8     8 0 10 sub output_code { $_[0]->output ($_[1]) }
319              
320             ##############################################################################
321             # Document initialization
322             ##############################################################################
323              
324             # Set up various things that have to be initialized on a per-document basis.
325             sub start_document {
326 40     40 0 64 my ($self, $attrs) = @_;
327 40 100 66     121 if ($$attrs{contentless} && !$$self{ALWAYS_EMIT_SOMETHING}) {
328 1         2 $$self{CONTENTLESS} = 1;
329             } else {
330 39         50 delete $$self{CONTENTLESS};
331             }
332 40         65 my $margin = $$self{opt_indent} + $$self{opt_margin};
333              
334             # Initialize a few per-document variables.
335 40         67 $$self{INDENTS} = []; # Stack of indentations.
336 40         84 $$self{MARGIN} = $margin; # Default left margin.
337 40         118 $$self{PENDING} = [[]]; # Pending output.
338              
339             # We have to redo encoding handling for each document.
340 40         67 $$self{ENCODING} = '';
341              
342             # When UTF-8 output is set, check whether our output file handle already
343             # has a PerlIO encoding layer set. If it does not, we'll need to encode
344             # our output before printing it (handled in the output() sub). Wrap the
345             # check in an eval to handle versions of Perl without PerlIO.
346 40         56 $$self{ENCODE} = 0;
347 40 100       71 if ($$self{opt_utf8}) {
348 2         2 $$self{ENCODE} = 1;
349 2         3 eval {
350 2         4 my @options = (output => 1, details => 1);
351 2         11 my $flag = (PerlIO::get_layers ($$self{output_fh}, @options))[-1];
352 2 50       14 if ($flag & PerlIO::F_UTF8 ()) {
353 2         2 $$self{ENCODE} = 0;
354 2         4 $$self{ENCODING} = 'UTF-8';
355             }
356             };
357             }
358              
359 40         96 return '';
360             }
361              
362             # Handle the end of the document. The only thing we do is handle dying on POD
363             # errors, since Pod::Parser currently doesn't.
364             sub end_document {
365 40     40 0 60 my ($self) = @_;
366 40 100 66     130 if ($$self{complain_die} && $self->errors_seen) {
367 1         219 croak ("POD document had syntax errors");
368             }
369             }
370              
371             ##############################################################################
372             # Text blocks
373             ##############################################################################
374              
375             # Intended for subclasses to override, this method returns text with any
376             # non-printing formatting codes stripped out so that length() correctly
377             # returns the length of the text. For basic Pod::Text, it does nothing.
378             sub strip_format {
379 49     49 0 97 my ($self, $string) = @_;
380 49         80 return $string;
381             }
382              
383             # This method is called whenever an =item command is complete (in other words,
384             # we've seen its associated paragraph or know for certain that it doesn't have
385             # one). It gets the paragraph associated with the item as an argument. If
386             # that argument is empty, just output the item tag; if it contains a newline,
387             # output the item tag followed by the newline. Otherwise, see if there's
388             # enough room for us to output the item tag in the margin of the text or if we
389             # have to put it on a separate line.
390             sub item {
391 136     136 1 212 my ($self, $text) = @_;
392 136         186 my $tag = $$self{ITEM};
393 136 50       217 unless (defined $tag) {
394 0         0 carp "Item called without tag";
395 0         0 return;
396             }
397 136         160 undef $$self{ITEM};
398              
399             # Calculate the indentation and margin. $fits is set to true if the tag
400             # will fit into the margin of the paragraph given our indentation level.
401 136         153 my $indent = $$self{INDENTS}[-1];
402 136 50       193 $indent = $$self{opt_indent} unless defined $indent;
403 136         205 my $margin = ' ' x $$self{opt_margin};
404 136         275 my $tag_length = length ($self->strip_format ($tag));
405 136         257 my $fits = ($$self{MARGIN} - $indent >= $tag_length + 1);
406              
407             # If the tag doesn't fit, or if we have no associated text, print out the
408             # tag separately. Otherwise, put the tag in the margin of the paragraph.
409 136 100 100     689 if (!$text || $text =~ /^\s+$/ || !$fits) {
      100        
410 39         55 my $realindent = $$self{MARGIN};
411 39         47 $$self{MARGIN} = $indent;
412 39         62 my $output = $self->reformat ($tag);
413 39 100 66     108 $output =~ s/^$margin /$margin:/ if ($$self{opt_alt} && $indent > 0);
414 39         155 $output =~ s/\n*$/\n/;
415              
416             # If the text is just whitespace, we have an empty item paragraph;
417             # this can result from =over/=item/=back without any intermixed
418             # paragraphs. Insert some whitespace to keep the =item from merging
419             # into the next paragraph.
420 39 100 100     153 $output .= "\n" if $text && $text =~ /^\s*$/;
421              
422 39         94 $self->output ($output);
423 39         187 $$self{MARGIN} = $realindent;
424 39 100 100     156 $self->output ($self->reformat ($text)) if ($text && $text =~ /\S/);
425             } else {
426 97         180 my $space = ' ' x $indent;
427 97 100       164 $space =~ s/^$margin /$margin:/ if $$self{opt_alt};
428 97         178 $text = $self->reformat ($text);
429 97 100 66     213 $text =~ s/^$margin /$margin:/ if ($$self{opt_alt} && $indent > 0);
430 97         136 my $tagspace = ' ' x $tag_length;
431 97 50       917 $text =~ s/^($space)$tagspace/$1$tag/ or warn "Bizarre space in item";
432 97         238 $self->output ($text);
433             }
434             }
435              
436             # Handle a basic block of text. The only tricky thing here is that if there
437             # is a pending item tag, we need to format this as an item paragraph.
438             sub cmd_para {
439 394     394 0 603 my ($self, $attrs, $text) = @_;
440 394         1176 $text =~ s/\s+$/\n/;
441 394 100       640 if (defined $$self{ITEM}) {
442 87         209 $self->item ($text . "\n");
443             } else {
444 307         748 $self->output ($self->reformat ($text . "\n"));
445             }
446 394         2589 return '';
447             }
448              
449             # Handle a verbatim paragraph. Just print it out, but indent it according to
450             # our margin.
451             sub cmd_verbatim {
452 22     22 0 40 my ($self, $attrs, $text) = @_;
453 22 50       50 $self->item if defined $$self{ITEM};
454 22 50       63 return if $text =~ /^\s*$/;
455 22         73 $text =~ s/^(\n*)([ \t]*\S+)/$1 . (' ' x $$self{MARGIN}) . $2/gme;
  111         367  
456 22         435 $text =~ s/\s*$/\n\n/;
457 22         50 $self->output ($text);
458 22         149 return '';
459             }
460              
461             # Handle literal text (produced by =for and similar constructs). Just output
462             # it with the minimum of changes.
463             sub cmd_data {
464 2     2 0 4 my ($self, $attrs, $text) = @_;
465 2         5 $text =~ s/^\n+//;
466 2         8 $text =~ s/\n{0,2}$/\n/;
467 2         4 $self->output ($text);
468 2         3 return '';
469             }
470              
471             ##############################################################################
472             # Headings
473             ##############################################################################
474              
475             # The common code for handling all headers. Takes the header text, the
476             # indentation, and the surrounding marker for the alt formatting method.
477             sub heading {
478 79     79 0 145 my ($self, $text, $indent, $marker) = @_;
479 79 50       155 $self->item ("\n\n") if defined $$self{ITEM};
480 79         200 $text =~ s/\s+$//;
481 79 100       131 if ($$self{opt_alt}) {
482 1         4 my $closemark = reverse (split (//, $marker));
483 1         3 my $margin = ' ' x $$self{opt_margin};
484 1         4 $self->output ("\n" . "$margin$marker $text $closemark" . "\n\n");
485             } else {
486 78 50       151 $text .= "\n" if $$self{opt_loose};
487 78         158 my $margin = ' ' x ($$self{opt_margin} + $indent);
488 78         200 $self->output ($margin . $text . "\n");
489             }
490 79         444 return '';
491             }
492              
493             # First level heading.
494             sub cmd_head1 {
495 72     72 0 424 my ($self, $attrs, $text) = @_;
496 72         157 $self->heading ($text, 0, '====');
497             }
498              
499             # Second level heading.
500             sub cmd_head2 {
501 8     8 0 62 my ($self, $attrs, $text) = @_;
502 8         21 $self->heading ($text, $$self{opt_indent} / 2, '== ');
503             }
504              
505             # Third level heading.
506             sub cmd_head3 {
507 8     8 0 14 my ($self, $attrs, $text) = @_;
508 8         27 $self->heading ($text, $$self{opt_indent} * 2 / 3 + 0.5, '= ');
509             }
510              
511             # Fourth level heading.
512             sub cmd_head4 {
513 8     8 0 17 my ($self, $attrs, $text) = @_;
514 8         24 $self->heading ($text, $$self{opt_indent} * 3 / 4 + 0.5, '- ');
515             }
516              
517             ##############################################################################
518             # List handling
519             ##############################################################################
520              
521             # Handle the beginning of an =over block. Takes the type of the block as the
522             # first argument, and then the attr hash. This is called by the handlers for
523             # the four different types of lists (bullet, number, text, and block).
524             sub over_common_start {
525 66     66 0 110 my ($self, $attrs) = @_;
526 66 50       130 $self->item ("\n\n") if defined $$self{ITEM};
527              
528             # Find the indentation level.
529 66         84 my $indent = $$attrs{indent};
530 66 50 33     338 unless (defined ($indent) && $indent =~ /^\s*[-+]?\d{1,4}\s*$/) {
531 0         0 $indent = $$self{opt_indent};
532             }
533              
534             # Add this to our stack of indents and increase our current margin.
535 66         89 push (@{ $$self{INDENTS} }, $$self{MARGIN});
  66         118  
536 66         112 $$self{MARGIN} += ($indent + 0);
537 66         140 return '';
538             }
539              
540             # End an =over block. Takes no options other than the class pointer. Output
541             # any pending items and then pop one level of indentation.
542             sub over_common_end {
543 66     66 0 88 my ($self) = @_;
544 66 100       155 $self->item ("\n\n") if defined $$self{ITEM};
545 66         81 $$self{MARGIN} = pop @{ $$self{INDENTS} };
  66         104  
546 66         288 return '';
547             }
548              
549             # Dispatch the start and end calls as appropriate.
550 8     8 0 18 sub start_over_bullet { $_[0]->over_common_start ($_[1]) }
551 8     8 0 17 sub start_over_number { $_[0]->over_common_start ($_[1]) }
552 38     38 0 111 sub start_over_text { $_[0]->over_common_start ($_[1]) }
553 12     12 0 25 sub start_over_block { $_[0]->over_common_start ($_[1]) }
554 8     8 0 16 sub end_over_bullet { $_[0]->over_common_end }
555 8     8 0 16 sub end_over_number { $_[0]->over_common_end }
556 38     38 0 115 sub end_over_text { $_[0]->over_common_end }
557 12     12 0 18 sub end_over_block { $_[0]->over_common_end }
558              
559             # The common handler for all item commands. Takes the type of the item, the
560             # attributes, and then the text of the item.
561             sub item_common {
562 136     136 0 213 my ($self, $type, $attrs, $text) = @_;
563 136 100       264 $self->item if defined $$self{ITEM};
564              
565             # Clean up the text. We want to end up with two variables, one ($text)
566             # which contains any body text after taking out the item portion, and
567             # another ($item) which contains the actual item text. Note the use of
568             # the internal Pod::Simple attribute here; that's a potential land mine.
569 136         312 $text =~ s/\s+$//;
570 136         148 my ($item, $index);
571 136 100       286 if ($type eq 'bullet') {
    100          
572 16         20 $item = '*';
573             } elsif ($type eq 'number') {
574 16         17 $item = $$attrs{'~orig_content'};
575             } else {
576 104         112 $item = $text;
577 104         151 $item =~ s/\s*\n\s*/ /g;
578 104         116 $text = '';
579             }
580 136         166 $$self{ITEM} = $item;
581              
582             # If body text for this item was included, go ahead and output that now.
583 136 100       186 if ($text) {
584 32         170 $text =~ s/\s*$/\n/;
585 32         63 $self->item ($text);
586             }
587 136         439 return '';
588             }
589              
590             # Dispatch the item commands to the appropriate place.
591 16     16 0 19 sub cmd_item_bullet { my $self = shift; $self->item_common ('bullet', @_) }
  16         39  
592 16     16 0 25 sub cmd_item_number { my $self = shift; $self->item_common ('number', @_) }
  16         27  
593 104     104 0 126 sub cmd_item_text { my $self = shift; $self->item_common ('text', @_) }
  104         177  
594 0     0 0 0 sub cmd_item_block { my $self = shift; $self->item_common ('block', @_) }
  0         0  
595              
596             ##############################################################################
597             # Formatting codes
598             ##############################################################################
599              
600             # The simple ones.
601 10 50   10 0 25 sub cmd_b { return $_[0]{alt} ? "``$_[2]''" : $_[2] }
602 6 50   6 0 15 sub cmd_f { return $_[0]{alt} ? "\"$_[2]\"" : $_[2] }
603 11     11 0 18 sub cmd_i { return '*' . $_[2] . '*' }
604 4     4 0 9 sub cmd_x { return '' }
605              
606             # Apply a whole bunch of messy heuristics to not quote things that don't
607             # benefit from being quoted. These originally come from Barrie Slaymaker and
608             # largely duplicate code in Pod::Man.
609             sub cmd_c {
610 113     113 0 148 my ($self, $attrs, $text) = @_;
611              
612             # A regex that matches the portion of a variable reference that's the
613             # array or hash index, separated out just because we want to use it in
614             # several places in the following regex.
615 113         118 my $index = '(?: \[.*\] | \{.*\} )?';
616              
617             # Check for things that we don't want to quote, and if we find any of
618             # them, return the string with just a font change and no quoting.
619 113 100       1143 $text =~ m{
620             ^\s*
621             (?:
622             ( [\'\`\"] ) .* \1 # already quoted
623             | \` .* \' # `quoted'
624             | \$+ [\#^]? \S $index # special ($^Foo, $")
625             | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func
626             | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call
627             | [+-]? ( \d[\d.]* | \.\d+ ) (?: [eE][+-]?\d+ )? # a number
628             | 0x [a-fA-F\d]+ # a hex constant
629             )
630             \s*\z
631             }xo && return $text;
632              
633             # If we didn't return, go ahead and quote the text.
634             return $$self{opt_alt}
635 105 50       311 ? "``$text''"
636             : "$$self{LQUOTE}$text$$self{RQUOTE}";
637             }
638              
639             # Links reduce to the text that we're given, wrapped in angle brackets if it's
640             # a URL.
641             sub cmd_l {
642 110     110 0 187 my ($self, $attrs, $text) = @_;
643 110 100       200 if ($$attrs{type} eq 'url') {
644 6 100 66     31 if (not defined($$attrs{to}) or $$attrs{to} eq $text) {
    100          
645 3         54 return "<$text>";
646             } elsif ($$self{opt_nourls}) {
647 1         16 return $text;
648             } else {
649 2         28 return "$text <$$attrs{to}>";
650             }
651             } else {
652 104         170 return $text;
653             }
654             }
655              
656             ##############################################################################
657             # Backwards compatibility
658             ##############################################################################
659              
660             # The old Pod::Text module did everything in a pod2text() function. This
661             # tries to provide the same interface for legacy applications.
662             sub pod2text {
663 1     1 0 813 my @args;
664              
665             # This is really ugly; I hate doing option parsing in the middle of a
666             # module. But the old Pod::Text module supported passing flags to its
667             # entry function, so handle -a and -.
668 1         5 while ($_[0] =~ /^-/) {
669 0         0 my $flag = shift;
670 0 0       0 if ($flag eq '-a') { push (@args, alt => 1) }
  0 0       0  
671 0         0 elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) }
672             else {
673 0         0 unshift (@_, $flag);
674 0         0 last;
675             }
676             }
677              
678             # Now that we know what arguments we're using, create the parser.
679 1         5 my $parser = Pod::Text->new (@args);
680              
681             # If two arguments were given, the second argument is going to be a file
682             # handle. That means we want to call parse_from_filehandle(), which means
683             # we need to turn the first argument into a file handle. Magic open will
684             # handle the <&STDIN case automagically.
685 1 50       3 if (defined $_[1]) {
686 0         0 my @fhs = @_;
687 0         0 local *IN;
688 0 0       0 unless (open (IN, $fhs[0])) {
689 0         0 croak ("Can't open $fhs[0] for reading: $!\n");
690 0         0 return;
691             }
692 0         0 $fhs[0] = \*IN;
693 0         0 $parser->output_fh ($fhs[1]);
694 0         0 my $retval = $parser->parse_file ($fhs[0]);
695 0         0 my $fh = $parser->output_fh ();
696 0         0 close $fh;
697 0         0 return $retval;
698             } else {
699 1         4 $parser->output_fh (\*STDOUT);
700 1         5 return $parser->parse_file (@_);
701             }
702             }
703              
704             # Reset the underlying Pod::Simple object between calls to parse_from_file so
705             # that the same object can be reused to convert multiple pages.
706             sub parse_from_file {
707 34     34 1 21943 my $self = shift;
708 34         134 $self->reinit;
709              
710             # Fake the old cutting option to Pod::Parser. This fiddles with internal
711             # Pod::Simple state and is quite ugly; we need a better approach.
712 34 100       810 if (ref ($_[0]) eq 'HASH') {
713 1         1 my $opts = shift @_;
714 1 50 33     6 if (defined ($$opts{-cutting}) && !$$opts{-cutting}) {
715 1         2 $$self{in_pod} = 1;
716 1         2 $$self{last_was_blank} = 1;
717             }
718             }
719              
720             # Do the work.
721 34         121 my $retval = $self->Pod::Simple::parse_from_file (@_);
722              
723             # Flush output, since Pod::Simple doesn't do this. Ideally we should also
724             # close the file descriptor if we had to open one, but we can't easily
725             # figure this out.
726 33         819 my $fh = $self->output_fh ();
727 33         237 my $oldfh = select $fh;
728 33         77 my $oldflush = $|;
729 33         760 $| = 1;
730 33         102 print $fh '';
731 33         55 $| = $oldflush;
732 33         140 select $oldfh;
733 33         100 return $retval;
734             }
735              
736             # Pod::Simple failed to provide this backward compatibility function, so
737             # implement it ourselves. File handles are one of the inputs that
738             # parse_from_file supports.
739             sub parse_from_filehandle {
740 1     1 0 8 my $self = shift;
741 1         5 $self->parse_from_file (@_);
742             }
743              
744             # Pod::Simple's parse_file doesn't set output_fh. Wrap the call and do so
745             # ourself unless it was already set by the caller, since our documentation has
746             # always said that this should work.
747             sub parse_file {
748 39     39 1 2201 my ($self, $in) = @_;
749 39 50       84 unless (defined $$self{output_fh}) {
750 0         0 $self->output_fh (\*STDOUT);
751             }
752 39         120 return $self->SUPER::parse_file ($in);
753             }
754              
755             # Do the same for parse_lines, just to be polite. Pod::Simple's man page
756             # implies that the caller is responsible for setting this, but I don't see any
757             # reason not to set a default.
758             sub parse_lines {
759 126     126 1 22338 my ($self, @lines) = @_;
760 126 50       282 unless (defined $$self{output_fh}) {
761 0         0 $self->output_fh (\*STDOUT);
762             }
763 126         359 return $self->SUPER::parse_lines (@lines);
764             }
765              
766             # Likewise for parse_string_document.
767             sub parse_string_document {
768 2     2 1 3363 my ($self, $doc) = @_;
769 2 50       5 unless (defined $$self{output_fh}) {
770 0         0 $self->output_fh (\*STDOUT);
771             }
772 2         9 return $self->SUPER::parse_string_document ($doc);
773             }
774              
775             ##############################################################################
776             # Module return value and documentation
777             ##############################################################################
778              
779             1;
780             __END__