package Tree::Template::Declare; use strict; use warnings; use Sub::Exporter; use Devel::Caller 'caller_args'; use Carp; use Data::Dumper; our $VERSION='0.1'; { my $exporter=Sub::Exporter::build_exporter({ groups => { default => \&_build_group, }, }); sub import { my ($pack,@rest)=@_; if (@rest) { @_=($pack,-default => {@rest}); } goto $exporter; } } sub _build_group { my ($class,$name,$args,$coll)=@_; my $builder=$args->{builder}; if (!ref($builder)) { my $builder_pkg=$builder; if ($builder_pkg=~m{\A \+(\w+) \z}smx) { $builder_pkg="Tree::Template::Declare::$1"; } eval "require $builder_pkg"; croak "Can't load $builder_pkg: $@" if $@; if ($builder_pkg->can('new')) { $builder=$builder_pkg->new(); } else { $builder=$builder_pkg; } } my $additional_exports={}; if ($builder->can('_additional_exports')) { $additional_exports=$builder->_additional_exports(); } my @current_node=(undef); return { tree => sub(&) { my $tree=$builder->new_tree(); { local $current_node[0]=$tree; $_[0]->(caller_args(1)); } return $builder->finalize_tree($tree); }, node => sub (&) { my $node=$builder->new_node(); { local $current_node[0]=$node; $_[0]->(caller_args(1)); } if ($current_node[0]) { $builder->add_child_node($current_node[0],$node); } return $node; }, name => sub ($) { $builder->set_node_name($current_node[0],$_[0]); return; }, attribs => sub { my %attrs=@_; $builder->set_node_attributes($current_node[0],\%attrs); return; }, %$additional_exports, }; } 1;