File Coverage

blib/lib/Pod/Tree.pm
Criterion Covered Total %
statement 112 149 75.1
branch 21 32 65.6
condition 1 3 33.3
subroutine 20 26 76.9
pod 13 13 100.0
total 167 223 74.8


line stmt bran cond sub pod time code
1             # Copyright (c) 1999-2009 by Steven McDougall. This module is free
2             # software; you can redistribute it and/or modify it under the same
3             # terms as Perl itself.
4              
5             package Pod::Tree;
6 18     18   588721 use 5.006;
  18         143  
7              
8 18     18   112 use strict;
  18         40  
  18         562  
9 18     18   100 use warnings;
  18         43  
  18         589  
10 18     18   5032 use IO::File;
  18         103221  
  18         2769  
11 18     18   17388 use Pod::Tree::Node;
  18         95  
  18         407  
12 18     18   7570 use Pod::Tree::Stream;
  18         39  
  18         10506  
13              
14             our $VERSION = '1.29';
15              
16             sub new {
17 84     84 1 36550 my $class = shift;
18 84         288 my $tree = {
19             loaded => 0,
20             paragraphs => []
21             };
22 84         227 bless $tree, $class;
23             }
24              
25             sub load_file {
26 75     75 1 257 my ( $tree, $file, %options ) = @_;
27              
28 75         385 Pod::Tree::Node->set_filename($file);
29              
30 75         339 my $fh = IO::File->new;
31 75 50       2329 $fh->open($file) or return '';
32 75         3293 $tree->load_fh( $fh, %options );
33              
34 75         245 Pod::Tree::Node->set_filename("");
35 75         1187 1;
36             }
37              
38             sub load_fh {
39 77     77 1 221 my ( $tree, $fh, %options ) = @_;
40              
41 77         203 $tree->{in_pod} = 0;
42 77         218 $tree->_load_options(%options);
43 77         134 my $limit = $tree->{limit};
44              
45 77         420 my $stream = Pod::Tree::Stream->new($fh);
46 77         133 my $paragraph;
47             my @paragraphs;
48 77         182 while ( $paragraph = $stream->get_paragraph ) {
49 2079         3295 push @paragraphs, $paragraph;
50 2079 50 33     4554 $limit and $limit == @paragraphs and last;
51             }
52              
53 77         227 $tree->{paragraphs} = \@paragraphs;
54 77         249 $tree->_parse;
55             }
56              
57             sub load_string {
58 5     5 1 26 my ( $tree, $string, %options ) = @_;
59              
60 5         160 my @chunks = split /( \n\s*\n | \r\s*\r | \r\n\s*\r\n )/x, $string;
61              
62 5         8 my (@paragraphs);
63 5         16 while (@chunks) {
64 167         324 push @paragraphs, join '', splice @chunks, 0, 2;
65             }
66              
67 5         21 $tree->load_paragraphs( \@paragraphs, %options );
68             }
69              
70             sub load_paragraphs {
71 7     7 1 20 my ( $tree, $paragraphs, %options ) = @_;
72              
73 7         15 $tree->{in_pod} = 1;
74 7         24 $tree->_load_options(%options);
75              
76 7         11 my $limit = $tree->{limit};
77 7         52 my @paragraphs = @$paragraphs;
78 7 50       17 $limit and splice @paragraphs, $limit;
79              
80 7         14 $tree->{paragraphs} = \@paragraphs;
81 7         16 $tree->_parse;
82             }
83              
84 51     51 1 148 sub loaded { shift->{'loaded'} }
85              
86             sub _load_options {
87 84     84   144 my ( $tree, %options ) = @_;
88              
89 84         119 my ( $key, $value );
90 84         305 while ( ( $key, $value ) = each %options ) {
91 4         14 $tree->{$key} = $value;
92             }
93             }
94              
95             sub _parse {
96 84     84   122 my $tree = shift;
97              
98 84         227 $tree->_make_nodes;
99 84         219 $tree->_make_for;
100 84         211 $tree->_make_sequences;
101              
102 84         151 my $root = $tree->{root};
103              
104 84         244 $root->parse_links;
105 84         241 $root->unescape;
106 84         246 $root->consolidate;
107 84         253 $root->make_lists;
108              
109 84         377 $tree->{'loaded'} = 1;
110             }
111              
112             sub _add_paragraph {
113 0     0   0 my ( $tree, $paragraph ) = @_;
114              
115 0         0 for ($paragraph) {
116 0 0       0 /^=cut/ and do {
117 0         0 $tree->{in_pod} = 0;
118 0         0 last;
119             };
120 0 0       0 $tree->{in_pod} and do {
121 0         0 push @{ $tree->{paragraphs} }, $paragraph;
  0         0  
122 0         0 last;
123             };
124 0 0       0 /^=\w/ and do {
125 0         0 $tree->{in_pod} = 1;
126 0         0 push @{ $tree->{paragraphs} }, $paragraph;
  0         0  
127 0         0 last;
128             };
129             }
130             }
131              
132             my %Command = map { $_ => 1 } qw(=pod =cut
133             =head1 =head2 =head3 =head4
134             =over =item =back
135             =for =begin =end);
136              
137             sub _make_nodes {
138 84     84   122 my $tree = shift;
139 84         145 my $paragraphs = $tree->{paragraphs};
140 84         120 my $in_pod = $tree->{in_pod};
141 84         110 my @children;
142              
143 84         183 for my $paragraph (@$paragraphs) {
144 2389         5561 my ($word) = split( /\s/, $paragraph );
145 2389         2758 my $node;
146              
147 2389 100       2998 if ($in_pod) {
148 2257 100       4294 if ( $paragraph =~ /^\s/ ) {
    100          
149 79         231 $node = Pod::Tree::Node->verbatim($paragraph);
150             }
151             elsif ( $Command{$word} ) {
152 1152         1929 $node = Pod::Tree::Node->command($paragraph);
153 1152         1471 $in_pod = $word ne '=cut';
154             }
155             else {
156 1026         1768 $node = Pod::Tree::Node->ordinary($paragraph);
157             }
158             }
159             else {
160 132 100       281 if ( $Command{$word} ) {
161 88         400 $node = Pod::Tree::Node->command($paragraph);
162 88         191 $in_pod = $word ne '=cut';
163             }
164             else {
165 44         153 $node = Pod::Tree::Node->code($paragraph);
166             }
167             }
168              
169 2389         3602 push @children, $node;
170             }
171              
172 84         264 $tree->{root} = Pod::Tree::Node->root( \@children );
173             }
174              
175             sub _make_for {
176 84     84   135 my $tree = shift;
177 84         138 my $root = $tree->{root};
178 84         188 my $old = $root->get_children;
179              
180 84         110 my @new;
181 84         192 while (@$old) {
182 2357         2534 my $node = shift @$old;
183 2357 100       3370 $node->is_c_for and $node->force_for;
184 2357 100       3548 $node->is_c_begin and $node->parse_begin($old);
185 2357         3883 push @new, $node;
186             }
187              
188 84         231 $root->set_children( \@new );
189             }
190              
191             sub _make_sequences {
192 84     84   114 my $tree = shift;
193 84         112 my $root = $tree->{root};
194 84         182 my $nodes = $root->get_children;
195              
196 84         155 for my $node (@$nodes) {
197 2357 100       3717 $node->is_code and next;
198 2313 100       3790 $node->is_verbatim and next;
199 2242 100       3458 $node->is_for and next;
200 2212         3385 $node->make_sequences;
201             }
202             }
203              
204             sub dump {
205 15     15 1 95 my $tree = shift;
206 15         49 $tree->{root}->dump;
207             }
208              
209 129     129 1 392 sub get_root { shift->{root} }
210              
211             sub set_root {
212 0     0 1 0 my ( $tree, $root ) = @_;
213 0         0 $tree->{root} = $root;
214             }
215              
216             sub push {
217 0     0 1 0 my ( $tree, @nodes ) = @_;
218 0         0 my $root = $tree->{root};
219 0         0 my $children = $root->get_children;
220 0         0 push @$children, @nodes;
221             }
222              
223             sub pop {
224 0     0 1 0 my $tree = shift;
225 0         0 my $root = $tree->get_root;
226 0         0 my $children = $root->get_children;
227 0         0 pop @$children;
228             }
229              
230             sub walk {
231 0     0 1 0 my ( $tree, $sub ) = @_;
232              
233 0         0 my $root = $tree->get_root;
234 0         0 _walk( $root, $sub );
235             }
236              
237             sub _walk {
238 0     0   0 my ( $tree, $sub ) = @_;
239              
240 0         0 my $descend = &$sub($tree); # :TRICKY: sub can modify node
241 0 0       0 $descend or return;
242              
243 0         0 my $node = $tree;
244              
245 0         0 my $children = $node->get_children;
246 0         0 for my $child (@$children) {
247 0         0 _walk( $child, $sub );
248             }
249              
250 0         0 my $siblings = $node->get_siblings;
251 0         0 for my $sibling (@$siblings) {
252 0         0 _walk( $sibling, $sub );
253             }
254             }
255              
256             sub has_pod {
257 63     63 1 108 my $tree = shift;
258 63         139 my $root = $tree->get_root;
259 63         154 my $children = $root->get_children;
260              
261 63         134 scalar grep { $_->get_type ne 'code' } @$children;
  824         1164  
262             }
263              
264             1
265              
266             __END__