File Coverage

blib/lib/Tree/Template/Declare.pm
Criterion Covered Total %
statement 57 58 98.2
branch 10 16 62.5
condition 4 6 66.6
subroutine 14 14 100.0
pod n/a
total 85 94 90.4


line stmt bran cond sub pod time code
1             package Tree::Template::Declare;
2             {
3             $Tree::Template::Declare::DIST = 'Tree-Template-Declare';
4             }
5             $Tree::Template::Declare::VERSION = '0.7';
6 4     4   175973 use strict;
  4         7  
  4         146  
7 4     4   14 use warnings;
  4         4  
  4         66  
8 4     4   1786 use Sub::Exporter;
  4         29824  
  4         16  
9 4     4   2075 use Devel::Caller 'caller_args';
  4         8469  
  4         205  
10 4     4   19 use Carp;
  4         3  
  4         144  
11 4     4   47 use 5.006;
  4         7  
  4         1890  
12              
13             {
14             my $exporter=Sub::Exporter::build_exporter({
15             groups => {
16             default => \&_build_group,
17             },
18             });
19              
20             sub import {
21 5     5   618 my ($pack,@rest)=@_;
22              
23 5 50       13 if (@rest) {
24 5         35 @_=($pack,-default => {@rest});
25             }
26 5         14 goto $exporter;
27             }
28             }
29              
30             our @nodes_stack;
31              
32             sub _build_group {
33 5     5   503 my ($class,$name,$args,$coll)=@_;
34              
35 5         7 my $builder=$args->{builder};
36              
37 5 50       12 if (! ref $builder) {
38 5         6 my $builder_pkg=$builder;
39 5 50       29 if ($builder_pkg=~m{\A [+](\w+) \z}smx) {
40 5         15 $builder_pkg="Tree::Template::Declare::$1";
41             }
42 5 50       265 eval "require $builder_pkg" ## no critic (ProhibitStringyEval)
43             or croak "Can't load $builder_pkg: $@"; ## no critic (ProhibitPunctuationVars)
44              
45 5 50       56 if ($builder_pkg->can('new')) {
46 5         14 $builder=$builder_pkg->new();
47             }
48             else {
49 0         0 $builder=$builder_pkg;
50             }
51             }
52              
53             my $normal_exports= {
54             tree => sub(&) {
55 5     5   11257 my $tree=$builder->new_tree();
56              
57 5         12 unshift @nodes_stack,$tree;
58 5         22 $_[0]->(caller_args(1));
59 5         12 shift @nodes_stack;
60              
61 5         14 return $builder->finalize_tree($tree);
62             },
63             node => sub (&) {
64 26     26   234 my $node=$builder->new_node();
65              
66 26         494 unshift @nodes_stack, $node;
67 26         48 $_[0]->(caller_args(1));
68 26         73 shift @nodes_stack;
69              
70 26   66     51 my $scalar_context=defined wantarray && !wantarray;
71 26 100 66     86 if (@nodes_stack && !$scalar_context) {
72 23         44 $builder->add_child_node($nodes_stack[0],$node);
73             }
74 26         529 return $node;
75             },
76             attach_nodes => sub {
77 1 50   1   5 if (@nodes_stack) {
78 1         1 for my $newnode (@_) {
79 3         78 $builder->add_child_node($nodes_stack[0],
80             $newnode);
81             }
82             }
83             },
84             name => sub ($) {
85 26     26   453 $builder->set_node_name($nodes_stack[0],$_[0]);
86 26         333 return;
87             },
88             attribs => sub {
89 13     13   36 my %attrs=@_;
90 13         29 $builder->set_node_attributes($nodes_stack[0],\%attrs);
91 13         46 return;
92             },
93 3     3   11 detached => sub($) { return scalar $_[0] },
94 5         71 };
95 5 100       37 if ($builder->can('_munge_exports')) {
96 1         3 return $builder->_munge_exports($normal_exports,\@nodes_stack);
97             }
98             else {
99 4         16 return $normal_exports;
100             }
101             }
102              
103             1;
104              
105             =pod
106              
107             =encoding UTF-8
108              
109             =head1 NAME
110              
111             Tree::Template::Declare - easily build tree structures
112              
113             =head1 VERSION
114              
115             version 0.7
116              
117             =head1 SYNOPSIS
118              
119             use Tree::Template::Declare builder => '+DAG_Node';
120              
121             my $tree=tree {
122             node {
123             name 'root';
124             attribs name => 'none';
125             node {
126             name 'first';
127             attribs name => 'number_1';
128             attribs other => 'some';
129             };
130             node {
131             name 'second';
132             };
133             };
134             };
135              
136             =head1 FUNCTIONS
137              
138             For details on the implementation of these functions, see the
139             L section, and the documentation of your chosen builder.
140              
141             =head2 C
142              
143             This function takes a code ref or a block, inside which calls to
144             C should be made, and returns a properly constructed tree
145             containing those nodes.
146              
147             Uses the builder's C and C.
148              
149             =head2 C
150              
151             This function takes a code ref or a block, inside which calls to
152             C, C, and C should be made, and returns the node.
153              
154             If I called in scalar context, it also adds the node to the
155             "calling" node or tree.
156              
157             Uses the builder's C and C.
158              
159             =head2 C
160              
161             Alias for C, so that you can say C
162             without having to worry about the calling context.
163              
164             =head2 C
165              
166             This function takes a list of nodes, and adds them (in order) to the
167             "calling" node or tree. You should only use this with nodes you
168             obtained by calling C in scalar context.
169              
170             Uses the builder's C.
171              
172             =head2 C
173              
174             This function takes a scalar, and sets the name of the current node to
175             the value of that scalar.
176              
177             Uses the builder's C.
178              
179             =head2 C
180              
181             This function takes a hash (not a hash ref), and sets the attributes
182             of the current node.
183              
184             Uses the builder's C.
185              
186             =head1 BUILDER
187              
188             To actually create nodes and trees, this module uses helper classes
189             called "builders". You must always specify a builder package, class or
190             object with the C option in the C line.
191              
192             If the builder is an object, the methods discussed below will be
193             called on it; if it's a class (i.e. a package that has a C
194             function), they will be called on an instance created by calling
195             C without parameters; otherwise they will be called as class
196             methods.
197              
198             The builder must implement these methods:
199              
200             =over
201              
202             =item C
203              
204             $tree = $current_node = $builder->new_tree();
205              
206             returns a tree object; that object will be set as the current node
207             within the code passed to the C function
208              
209             =item C
210              
211             return $builder->finalize_tree($tree);
212              
213             this function will be passed the object returned by C, after
214             the code passed to C has been executed; the result of
215             C will be the result of C
216              
217             =item C
218              
219             $current_node=$builder->new_node();
220              
221             returns a new, unattached node
222              
223             =item C
224              
225             $builder->set_node_name($current_node, $name);
226              
227             sets the name of the node (e.g. for SGML-like trees, this is the "tag
228             name")
229              
230             =item C
231              
232             $builder->set_node_attributes($current_node, \%attribs);
233              
234             sets attributes of the node; it should not remove previously-set attributes
235              
236             =item C
237              
238             $builder->add_child_node($parent_node, $child_node);
239              
240             adds the second node at the end of the children list of the first node
241              
242             =back
243              
244             The builder can also implement an C<_munge_exports> method. If it
245             does, C<_munge_exports> will be called with:
246              
247             =over 4
248              
249             =item *
250              
251             a hash ref consisting of the functions that C
252             wants to export,
253              
254             =item *
255              
256             an array ref, whose first element will be the current node whenever
257             the user calls an exported function
258              
259             =back
260              
261             C<_munge_exports> should return a hash ref with the functions that
262             will actually be exported.
263              
264             See L, in particular the section on group builders, for
265             details. See L and
266             L for examples.
267              
268             =head1 IMPORTING
269              
270             This module uses L, although it munges the C list
271             before passing it to L. A line like:
272              
273             use Tree::Template::Declare @something;
274              
275             becomes a call to L's export sub like:
276              
277             $export->('Tree::Template::Declare',-default => {@something});
278              
279             See L's documentation for things like renaming the
280             imports.
281              
282             You can C this module more than once, with different builders and
283             different names for the imports:
284              
285             use Tree::Template::Declare -prefix=> 'x', builder => '+LibXML';
286             use Tree::Template::Declare -prefix=> 'd', builder => '+DAG_Node';
287              
288             =head1 KNOWN ISSUES & BUGS
289              
290             =over 4
291              
292             =item *
293              
294             C<_munge_exports> is ugly
295              
296             =item *
297              
298             the context-sensitivity of C might not be the best way to DWIM
299             for the creation of detached nodes
300              
301             =back
302              
303             =head1 AUTHOR
304              
305             Gianni Ceccarelli
306              
307             =head1 COPYRIGHT AND LICENSE
308              
309             This software is copyright (c) 2015 by Gianni Ceccarelli .
310              
311             This is free software; you can redistribute it and/or modify it under
312             the same terms as the Perl 5 programming language system itself.
313              
314             =cut
315              
316             __END__