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   683236 use 5.006;
  18         151  
7              
8 18     18   117 use strict;
  18         39  
  18         479  
9 18     18   111 use warnings;
  18         55  
  18         604  
10 18     18   5524 use IO::File;
  18         100309  
  18         2381  
11 18     18   9452 use Pod::Tree::Node;
  18         93  
  18         473  
12 18     18   7616 use Pod::Tree::Stream;
  18         47  
  18         12666  
13              
14             our $VERSION = '1.31';
15              
16             sub new {
17 84     84 1 43719 my $class = shift;
18 84         344 my $tree = {
19             loaded => 0,
20             paragraphs => []
21             };
22 84         262 bless $tree, $class;
23             }
24              
25             sub load_file {
26 75     75 1 321 my ( $tree, $file, %options ) = @_;
27              
28 75         472 Pod::Tree::Node->set_filename($file);
29              
30 75         416 my $fh = IO::File->new;
31 75 50       2946 $fh->open($file) or return '';
32 75         4003 $tree->load_fh( $fh, %options );
33              
34 75         309 Pod::Tree::Node->set_filename("");
35 75         1509 1;
36             }
37              
38             sub load_fh {
39 77     77 1 293 my ( $tree, $fh, %options ) = @_;
40              
41 77         261 $tree->{in_pod} = 0;
42 77         286 $tree->_load_options(%options);
43 77         161 my $limit = $tree->{limit};
44              
45 77         519 my $stream = Pod::Tree::Stream->new($fh);
46 77         171 my $paragraph;
47             my @paragraphs;
48 77         230 while ( $paragraph = $stream->get_paragraph ) {
49 2079         3627 push @paragraphs, $paragraph;
50 2079 50 33     5404 $limit and $limit == @paragraphs and last;
51             }
52              
53 77         261 $tree->{paragraphs} = \@paragraphs;
54 77         319 $tree->_parse;
55             }
56              
57             sub load_string {
58 5     5 1 29 my ( $tree, $string, %options ) = @_;
59              
60 5         219 my @chunks = split /( \n\s*\n | \r\s*\r | \r\n\s*\r\n )/x, $string;
61              
62 5         14 my (@paragraphs);
63 5         21 while (@chunks) {
64 167         391 push @paragraphs, join '', splice @chunks, 0, 2;
65             }
66              
67 5         24 $tree->load_paragraphs( \@paragraphs, %options );
68             }
69              
70             sub load_paragraphs {
71 7     7 1 23 my ( $tree, $paragraphs, %options ) = @_;
72              
73 7         17 $tree->{in_pod} = 1;
74 7         29 $tree->_load_options(%options);
75              
76 7         15 my $limit = $tree->{limit};
77 7         44 my @paragraphs = @$paragraphs;
78 7 50       19 $limit and splice @paragraphs, $limit;
79              
80 7         18 $tree->{paragraphs} = \@paragraphs;
81 7         21 $tree->_parse;
82             }
83              
84 51     51 1 185 sub loaded { shift->{'loaded'} }
85              
86             sub _load_options {
87 84     84   182 my ( $tree, %options ) = @_;
88              
89 84         142 my ( $key, $value );
90 84         392 while ( ( $key, $value ) = each %options ) {
91 4         15 $tree->{$key} = $value;
92             }
93             }
94              
95             sub _parse {
96 84     84   148 my $tree = shift;
97              
98 84         276 $tree->_make_nodes;
99 84         295 $tree->_make_for;
100 84         263 $tree->_make_sequences;
101              
102 84         209 my $root = $tree->{root};
103              
104 84         288 $root->parse_links;
105 84         304 $root->unescape;
106 84         317 $root->consolidate;
107 84         265 $root->make_lists;
108              
109 84         450 $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   151 my $tree = shift;
139 84         160 my $paragraphs = $tree->{paragraphs};
140 84         153 my $in_pod = $tree->{in_pod};
141 84         132 my @children;
142              
143 84         228 for my $paragraph (@$paragraphs) {
144 2389         6532 my ($word) = split( /\s/, $paragraph );
145 2389         3339 my $node;
146              
147 2389 100       3622 if ($in_pod) {
148 2257 100       5204 if ( $paragraph =~ /^\s/ ) {
    100          
149 79         222 $node = Pod::Tree::Node->verbatim($paragraph);
150             }
151             elsif ( $Command{$word} ) {
152 1152         2302 $node = Pod::Tree::Node->command($paragraph);
153 1152         1764 $in_pod = $word ne '=cut';
154             }
155             else {
156 1026         2163 $node = Pod::Tree::Node->ordinary($paragraph);
157             }
158             }
159             else {
160 132 100       343 if ( $Command{$word} ) {
161 88         544 $node = Pod::Tree::Node->command($paragraph);
162 88         208 $in_pod = $word ne '=cut';
163             }
164             else {
165 44         157 $node = Pod::Tree::Node->code($paragraph);
166             }
167             }
168              
169 2389         4323 push @children, $node;
170             }
171              
172 84         340 $tree->{root} = Pod::Tree::Node->root( \@children );
173             }
174              
175             sub _make_for {
176 84     84   157 my $tree = shift;
177 84         153 my $root = $tree->{root};
178 84         243 my $old = $root->get_children;
179              
180 84         149 my @new;
181 84         263 while (@$old) {
182 2357         2930 my $node = shift @$old;
183 2357 100       4260 $node->is_c_for and $node->force_for;
184 2357 100       4424 $node->is_c_begin and $node->parse_begin($old);
185 2357         4719 push @new, $node;
186             }
187              
188 84         301 $root->set_children( \@new );
189             }
190              
191             sub _make_sequences {
192 84     84   128 my $tree = shift;
193 84         150 my $root = $tree->{root};
194 84         211 my $nodes = $root->get_children;
195              
196 84         228 for my $node (@$nodes) {
197 2357 100       4498 $node->is_code and next;
198 2313 100       4595 $node->is_verbatim and next;
199 2242 100       4210 $node->is_for and next;
200 2212         4168 $node->make_sequences;
201             }
202             }
203              
204             sub dump {
205 15     15 1 104 my $tree = shift;
206 15         66 $tree->{root}->dump;
207             }
208              
209 129     129 1 506 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 137 my $tree = shift;
258 63         175 my $root = $tree->get_root;
259 63         179 my $children = $root->get_children;
260              
261 63         150 scalar grep { $_->get_type ne 'code' } @$children;
  824         1353  
262             }
263              
264             1
265              
266             __END__