File Coverage

blib/lib/Pod/Spell.pm
Criterion Covered Total %
statement 68 69 98.5
branch 34 40 85.0
condition 15 21 71.4
subroutine 13 14 92.8
pod 4 4 100.0
total 134 148 90.5


line stmt bran cond sub pod time code
1             package Pod::Spell;
2 5     5   329426 use 5.008;
  5         56  
3 5     5   32 use strict;
  5         8  
  5         103  
4 5     5   20 use warnings;
  5         8  
  5         1388  
5              
6             our $VERSION = '1.26';
7              
8             sub new {
9 6     6 1 7651 my ( $class, %args ) = @_;
10              
11 6         16 my $no_wide_chars = delete $args{no_wide_chars};
12 6 50       22 my $debug = exists $args{debug} ? delete $args{debug} : $ENV{PERL_POD_SPELL_DEBUG};
13              
14 6   33     23 my $stopwords = $args{stopwords} || do {
15             require Pod::Wordlist;
16             Pod::Wordlist->new(
17             _is_debug => $debug,
18             no_wide_chars => $no_wide_chars
19             )
20             };
21              
22 6         597 my $parser = Pod::Spell::_Processor->new;
23 6         26 $parser->stopwords($stopwords);
24 6         51 $parser->_is_debug($debug);
25 6 50       181 open my $output_fh, '>&:encoding(UTF-8)', \*STDOUT
26             or die "can't dup STDOUT: $!";
27 6         53 $parser->output_fh($output_fh);
28              
29 6         49 my %self = (
30             processor => $parser,
31             stopwords => $stopwords,
32             debug => $debug,
33             );
34              
35 6         34 bless \%self, $class
36             }
37              
38 2 100   2   322 sub _is_debug { (shift)->{debug} ? 1 : 0; }
39              
40 1     1 1 36 sub stopwords { (shift)->{stopwords} }
41              
42             sub parse_from_file {
43 0     0 1 0 shift->{processor}->parse_from_file(@_)
44             }
45              
46             sub parse_from_filehandle {
47 4     4 1 2206 shift->{processor}->parse_from_file(@_)
48             }
49              
50             package # Hide from indexing
51             Pod::Spell::_Processor;
52 5     5   755 use parent 'Pod::Simple';
  5         497  
  5         25  
53              
54 5     5   131718 use Text::Wrap ();
  5         11319  
  5         2543  
55              
56             __PACKAGE__->_accessorize(qw(
57             stopwords
58             _is_debug
59             ));
60              
61             sub new {
62 6     6   16 my $class = shift;
63 6         42 my $self = $class->SUPER::new(@_);
64 6         177 $self->accept_targets('stopwords');
65 6         145 return $self;
66             }
67              
68             my %track_elements = (
69             for => 1,
70             Verbatim => 1,
71             L => 1,
72             C => 1,
73             F => 1,
74             );
75              
76             sub _handle_element_start {
77 38     38   11888 my ($self, $element_name, $attr) = @_;
78             $self->{buffer} = ''
79 38 100       94 if !defined $self->{buffer};
80              
81 38 100       102 if ($track_elements{$element_name}) {
82 13         17 push @{ $self->{in_element} }, [ $element_name, $attr ];
  13         43  
83             }
84             }
85              
86             sub _handle_text {
87 36     36   294 my ($self, $text) = @_;
88              
89 36         49 my $in = $self->{in_element};
90 36 100 100     126 if ($in && @$in) {
91 14         18 my ($element_name, $attr) = @{$in->[-1]};
  14         28  
92 14 100 66     65 if ($element_name eq 'for' && $attr->{target_matching} eq 'stopwords') {
    100 33        
    100          
    50          
93             # this will match both for/begin and stopwords/:stopwords
94              
95 6 50       17 print "Stopword para: <$text>\n"
96             if $self->_is_debug;
97 6         433 $self->stopwords->learn_stopwords($text);
98 6         26 return;
99             }
100             # totally ignore verbatim sections
101             elsif ($element_name eq 'Verbatim') {
102 1         2 return;
103             }
104             elsif ($element_name eq 'L') {
105             return
106 1 50       4 if $attr->{'content-implicit'};
107             }
108             elsif ($element_name eq 'C' || $element_name eq 'F') {
109             # maintain word boundaries
110 6 100       30 my $pre = $text =~ s{\A\s+}{} ? ' ' : '';
111 6 100       20 my $post = $text =~ s{\s+\z}{} ? ' ' : '';
112             # if _ is joined with text before or after, it will be treated as
113             # a Perl token and the entire word ignored
114 6 50       13 $text = $pre . (length $text ? '_' : '') . $post;
115             }
116             }
117              
118 28         59 $self->{buffer} .= $text;
119             }
120              
121             sub _handle_element_end {
122 38     38   960 my ($self, $element_name) = @_;
123              
124 38         58 my $in = $self->{in_element};
125 38 100 100     143 if ($in && @$in && $in->[-1][0] eq $element_name) {
      100        
126 13         19 pop @$in;
127             }
128              
129             return
130 38 100       162 if $element_name !~ m{\A(?:Para|head\d|item-.*|over-block)\z};
131              
132 18         39 my $buffer = delete $self->{buffer};
133 18 100 66     75 if (!defined $buffer || !length $buffer) {
134 3         7 return;
135             }
136              
137 15         52 my $fh = $self->output_fh;
138              
139 15         95 my $out = $self->stopwords->strip_stopwords($buffer);
140              
141             # maintain exact output of older Pod::Parser based implementation
142 15 100       38 print { $fh } "\n"
  4         42  
143             if $element_name ne 'Para';
144              
145             return
146 15 100       39 if !length $out;
147              
148 12         22 local $Text::Wrap::huge = 'overflow';
149 12         18 print { $fh } Text::Wrap::wrap( '', '', $out ) . "\n\n";
  12         43  
150             }
151              
152             1;
153              
154             __END__