File Coverage

blib/lib/App/PodLinkCheck/ParseSections.pm
Criterion Covered Total %
statement 44 44 100.0
branch 9 10 90.0
condition 2 3 66.6
subroutine 11 11 100.0
pod 2 2 100.0
total 68 70 97.1


line stmt bran cond sub pod time code
1             # Copyright 2010, 2011, 2012, 2013, 2016 Kevin Ryde
2              
3             # This file is part of PodLinkCheck.
4              
5             # PodLinkCheck is free software; you can redistribute it and/or modify it
6             # under the terms of the GNU General Public License as published by the Free
7             # Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # PodLinkCheck is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with PodLinkCheck. If not, see <http://www.gnu.org/licenses/>.
17              
18             package App::PodLinkCheck::ParseSections;
19 1     1   455 use 5.006;
  1         2  
20 1     1   3 use strict;
  1         0  
  1         15  
21 1     1   3 use warnings;
  1         2  
  1         21  
22 1     1   3 use base 'Pod::Simple';
  1         1  
  1         647  
23              
24 1     1   25106 use vars '$VERSION';
  1         2  
  1         439  
25             $VERSION = 14;
26              
27             # uncomment this to run the ### lines
28             # use Smart::Comments;
29              
30             sub new {
31 7     7 1 5271   my ($class, $plc) = @_;
32 7         26   my $self = $class->SUPER::new;
33 7         134   $self->{(__PACKAGE__)}->{'sections'} = {};
34 7         20   $self->no_errata_section(1);
35 7         42   $self->preserve_whitespace(1);
36 7 50       30   if (! $plc->{'verbose'}) {
37 7         14     $self->no_whining(1);
38               }
39 7         31   return $self;
40             }
41              
42             sub sections_hashref {
43 6     6 1 44   my ($self) = @_;
44 6         9   return $self->{(__PACKAGE__)}->{'sections'};
45             }
46              
47             sub _handle_element_start {
48 18     18   1790   my ($self, $ename, $attr) = @_;
49             ### _handle_element_start(): $ename, $attr
50              
51             # Any of head1
52             # head2
53             # head3
54             # head4
55             # item-text
56             # item-bullet
57             # item-number
58 18 100       42   if ($ename =~ /^(head|item)/) {
59 6         7     $self->{(__PACKAGE__)}->{'item_text'} = '';
60               }
61              
62             # in_X is true when within an X<>, possibly a nested X<a X<b> c>
63             # although that's likely a mistake and probably meaningless
64 18         37   $self->{(__PACKAGE__)}->{'in_X'} += ($ename eq 'X');
65             }
66             sub _handle_text {
67 9     9   40   my ($self, $text) = @_;
68             ### _handle_text(): $text
69 9 100 66     36   if (exists $self->{(__PACKAGE__)}->{'item_text'}
70                  && ! $self->{(__PACKAGE__)}->{'in_X'}) {
71 6         13     $self->{(__PACKAGE__)}->{'item_text'} .= $text;
72               }
73             }
74             sub _handle_element_end {
75 18     18   314   my ($self, $ename) = @_;
76             ### _handle_element_end(): $ename
77              
78 18         19   $self->{(__PACKAGE__)}->{'in_X'} -= ($ename eq 'X');
79              
80 18 100       45   if ($ename =~ /^(head|item)/) {
81 6         10     my $section = delete $self->{(__PACKAGE__)}->{'item_text'};
82             ### section: $section
83              
84 6         8     $section = _collapse_whitespace ($section);
85 6         7     $self->{(__PACKAGE__)}->{'sections'}->{$section} = 1;
86              
87             # Like Pod::Checker take the first word, meaning up to the first
88             # whitespace, as a section name too, which is much used for
89             # cross-references to perlfunc.
90             #
91             # THINK-ABOUT-ME: CHI.pm is better treated by taking the first \w word
92             # so as to exclude parens etc.
93             #
94 6 100       18     if ($section =~ s/\s.*//) {
95             ### section one word: $section
96 3         6       $self->{(__PACKAGE__)}->{'sections'}->{$section} = 1;
97                 }
98               }
99             }
100              
101             sub _collapse_whitespace {
102 6     6   6   my ($str) = @_;
103 6         12   $str =~ s/\s+/ /g;
104 6         8   $str =~ s/^\s+//;
105 6         8   $str =~ s/\s+$//;
106 6         8   return $str;
107             }
108              
109             1;
110             __END__
111            
112             =for stopwords PodLinkCheck Ryde boolean hashref whitespace formatters
113            
114             =head1 NAME
115            
116             App::PodLinkCheck::ParseSections -- parse out section names from POD
117            
118             =head1 SYNOPSIS
119            
120             use App::PodLinkCheck::ParseSections;
121            
122             =head1 CLASS HIERARCHY
123            
124             Pod::Simple
125             App::PodLinkCheck::ParseSections
126            
127             =head1 DESCRIPTION
128            
129             This is a POD parser used by C<App::PodLinkCheck> to find section names in a
130             document. Its behaviour is specific to PodLinkCheck but might have other
131             use.
132            
133             =head1 FUNCTIONS
134            
135             =over
136            
137             =item C<$parser = App::PodLinkCheck::ParseSections-E<gt>new($options_hashref)>
138            
139             Create and return a new parser object.
140            
141             The default is to disable C<Pod::Simple> whining about dubious pod, because
142             C<App::PodLinkCheck> is just meant to check links. C<$options_hashref> can
143             have C<verbose> to give full messages from C<Pod::Simple>.
144            
145             $parser = App::PodLinkCheck::ParseSections->new({ verbose => 1 });
146            
147             It also works to set C<$parser-E<gt>no_whining()> as desired at any time.
148            
149             =item C<$parser-E<gt>parse_file($filename)>
150            
151             Parse the pod from C<$filename>. All the various C<Pod::Simple> parse input
152             styles can be used too.
153            
154             =item C<$hashref = $parser-E<gt>sections_hashref()>
155            
156             Return a hashref of the names of POD sections seen by C<$parser>. The keys
157             are the section names. The values are true (presently just 1).
158            
159             Sections names are mildly normalized by collapsing whitespace to a single
160             space each and removing leading and trailing whitespace. Believe that's
161             mostly how the pod formatters end up treating section names for linking
162             purposes. (That sort of treatment being the intention here.)
163            
164             The first word (of non-whitespace) of a section name is added as a hash
165             entry too. This is in the style of C<Pod::Checker> and is how the
166             formatters help links to function names in for example L<perlfunc>.
167            
168             The section names accumulate everything seen by C<$parser>. No attention is
169             paid to any "Document" start etc. Usually a new
170             C<App::PodLinkCheck::ParseSections> is used for each file (unless some union
171             of section names is in fact wanted).
172            
173             =back
174            
175             =head1 SEE ALSO
176            
177             L<App::PodLinkCheck>,
178             L<App::PodLinkCheck::ParseLinks>
179            
180             =head1 HOME PAGE
181            
182             http://user42.tuxfamily.org/podlinkcheck/index.html
183            
184             =head1 LICENSE
185            
186             Copyright 2010, 2011, 2012, 2013, 2016 Kevin Ryde
187            
188             PodLinkCheck is free software; you can redistribute it and/or modify it
189             under the terms of the GNU General Public License as published by the Free
190             Software Foundation; either version 3, or (at your option) any later
191             version.
192            
193             PodLinkCheck is distributed in the hope that it will be useful, but WITHOUT
194             ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
195             FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
196             more details.
197            
198             You should have received a copy of the GNU General Public License along with
199             PodLinkCheck. If not, see <http://www.gnu.org/licenses/>.
200            
201             =cut
202